鱼C论坛

 找回密码
 立即注册
查看: 2002|回复: 1

单元的cnpack很卡,求大佬指点迷津

[复制链接]
匿名鱼油
匿名鱼油  发表于 2021-11-20 16:52:48 |阅读模式
50鱼币
排除了代码过多的原因,其他同样的行数的单元就很好,就这个很卡,恳请大佬帮忙指点指点,谢谢

====================================================================================================
unit ObjPlayer;

interface
uses
  Windows, Classes, SysUtils, UInt64Lib, StrUtils, Grobal2, EDcode, Envir, ObjBase, ObjPetBooth,GameDB_SQL, WinlicenseSDK,  MapPoint,
  VersionManage, ObjPlayer_0_Base, PacketManageUnit, DateUtils;

type
  //玩家对象
  TPlayObject = class(TBasePlayObject)
    m_DearHuman: TPlayObject;
    m_MasterHuman: TPlayObject;
    m_GetWhisperHuman: TPlayObject;
     //ai参数

     m_boAI : Boolean;
     m_RunPos: TRunPos;
     m_boAIStart: Boolean;
     m_ManagedEnvir: TEnvirnoment; //挂机地图
    m_nPostion: Integer;
     m_PointManager: TPointManager;
    m_Path: TPath;

      start_x,start_y:Integer  ;
      m_nMoveFailCount:Integer  ;
      m_nround:Integer ;

      //new转移
       m_GuildTowerInfo: TGuildTowerInfo;
   m_dwStopMagic: array[1..199] of Integer;                                                        //禁止人物释放技能
    m_btBuffArr: array[1..MAX_BUFF_TICK] of Byte;                                                   //Buff效果持续时间标记
    m_dwBuffArrTick: array[1..MAX_BUFF_TICK] of LongWord;
    m_ErgumCount: TErgumCount;
    m_DealCreat: TBaseObject;                                                                       //交易的主动方
    m_boSuitSub: array[0..500] of Boolean;                                                          //套装属性
        m_ExemptHurt: TExemptHurt;
     m_ReduceSkillLevel: array[0..40] of byte;                                                       //41个魂佑技能等级
    m_ReduceSkillPoint: array[0..40] of byte;                                                       //41个魂佑技能点数  灵兽装备增加的


  private
    procedure ClientAddFriend(FriendName: string);
    procedure ClientDelFriend(FriendName: string);
    procedure ClientRespAddFriend(nRespCode: word; FriendName: string);
    procedure AddToFriendList(FriendName: string);
    procedure DelFromFriendList(FriendName: string);
    function ClientDropGold(nGold: Integer): Boolean;
    procedure ClientQueryBagItems();
    procedure ClientSendBagOrder();
    function ClientRide: Boolean;
    procedure ClearFree();
    function GetAmbitStatus(): Integer; override;
    function GetMagicExStatus(): byte; override;
    function GetFeature(BaseObject: TBaseObject): Integer; override;
    function GetFeatureEx(): byte; override;
    procedure StruckDamage(nDamage: Integer); override;
  public
    procedure KillMonsterFunc();
    procedure KillPlayerFunc();
    procedure CheckProwlMagic();                                                                    //检查是否有潜行
    procedure SendPetInfo(State: byte);
    procedure ClientRideOff;
    procedure SendMeOnlineState(State: byte; b: ShortInt = -1);
    procedure MakeWeaponUnlock();
    function PetStoreAddExp(nPetItemIdx, nExp, nDay: Integer; boEat: Boolean): Boolean; override;
    procedure SendTigerItem();
    procedure CheckStoreBagDupeItem;
  private
    m_sQueryName: string;
    function CheckEatItems(StdItem: pTStdItem): Boolean;
    procedure ClientQueryUserSet(ProcessMsg: pTProcessMessage);
    function IsDownPetItem(nMakeIndex: Integer): Boolean;
    function ClientDropItem(sItemName: string; nItemIdx: Integer): Boolean;
    procedure ClientQueryUserState(BaseObject: TBaseObject; nX, nY: Integer);
    function PetPickUpItem(nX, nY: Integer): Boolean;
    procedure ClientOpenDoor(nX, nY: Integer);
    function ClientTakeOnItems(btWhere: byte; nItemIdx: Integer; sItemName: string; boFlag: Boolean): Boolean;
    procedure ClientTakeOffItems(btWhere: byte; nItemIdx: Integer; sItemName: string);
    procedure ClientUseItems(nItemIdx: Integer; sItemName: string; nPackIdx: Integer);
    function UseStdmodeFunItem(StdItem: pTStdItem; boNew: Boolean = False): Boolean;
    procedure RefMyStatus;
    function ClientGetButchItem(BaseObject: TBaseObject; nX, nY: Integer; btDir: byte; var dwDelayTime: LongWord): Boolean;
    procedure ClientChangeMagicKey(nSkillIdx, nKey: Integer);
    procedure ClientMerchantDlgSelect(nParam1: Integer; sMsg: string; nType: Integer = 0);
    procedure ClientNamedStore(nParam1: Integer; nMakeIndex: Integer);
    procedure ClientSplitItem(nMakeIndex: Integer; nCount: Integer; boScript: Boolean);
    procedure RecordHomeXY(nParam1: Integer; nMapIdx: Integer); overload;
    procedure RecordHomeXY(nParam1: Integer; sMsg: string); overload;
    procedure ClientPerfectStoreMoveHome(nParam1: Integer; nMapIdx: Integer);
    procedure ClientQuerySlaverState;
    procedure ClientInput(nParam1: Integer; Data: string);
    procedure ClientMerchantQuerySellPrice(nParam1, nMakeIndex: Integer; sMsg: string);
    procedure ClientUserSellItem(nParam1, nMakeIndex: Integer; sMsg: string);
    procedure ClientUserBuyItem(nIdent, nParam1, nInt, nZz: Integer; sMsg: string; nType: Integer = 0);
    procedure ClientQueryRepairCost(nParam1, nInt: Integer; nRepairType: Integer; sMsg: string);
    procedure ClientRepairItem(nParam1, nInt: Integer; nRepairType: Integer; sMsg: string);
    function FindViewHum(PlayObject: TObject): TPlayObject;
    procedure ClientGropuClose();
    procedure ClientCreateGroup(sHumName: string);
    procedure ClientAddGroupMember(sHumName: string);
    procedure ClientDelGroupMember(sHumName: string);
    procedure ClientDealTry(sHumName: string);
    procedure ClientAddDealItem(nItemIdx: Integer; sItemName: string);
    procedure ClientDelDealItem(nItemIdx: Integer; sItemName: string);
    procedure ClientCancelDeal();
    procedure ClientChangeDealGold(nGold, nGameGold: Integer);
    procedure ClientDealEnd();
    procedure ClientStorageItem(NPC: TObject; nItemIdx: Integer; boFast:
      Boolean; sMsg: string);
    procedure ClientTakeBackStorageItem(NPC: TObject; nItemIdx: Integer; boFast:
      Boolean; sMsg: string);
    procedure ClientGetMinMap();
    procedure ClientMakeDrugItem(NPC: TObject; nItemName: string);
    procedure ClientOpenGuildDlg();
    procedure ClientGuildHome();
    procedure ClientGuildAddMember(sHumName: string);
    procedure ClientGuildDelMember(sHumName: string);
    procedure ClientGuildUpdateNotice(sNotict: string);
    procedure ClientGuildUpdateRankInfo(sRankInfo: string);
    procedure ClientGuildAlly();
    procedure ClientGuildBreakAlly(sGuildName: string);
    procedure ClientAdjustBonus(nPoint: Integer; sMsg: string);
    function ClientChangeDir(wIdent: word; nX, nY, nDir: Integer; var
      dwDelayTime: LongWord): Boolean;
    function ClientWalkXY(wIdent: word; nX, nY: Integer; boLateDelivery:
      Boolean; var dwDelayTime: LongWord): Boolean;
    //    function ClientHorseRunXY(wIdent: word; nX, nY: Integer; boLateDelivery:
    //      Boolean; var dwDelayTime: LongWord): Boolean;
    function ClientRunXY(wIdent: word; nX, nY: Integer; nFlag: Integer; var dwDelayTime: LongWord): Boolean;
    function ClientHitXY(wIdent: word; nX, nY, nDir, nMagicID: Integer;
      boLateDelivery: Boolean; var dwDelayTime: LongWord): Boolean;
    function ClientSitDownHit(nX, nY, nDir: Integer; var dwDelayTime: LongWord): Boolean;
    function ClientSpellXY(wIdent: word; nKey: Integer; nTargetX, nTargetY:
      Integer; TargeTBaseObject: TBaseObject; boLateDelivery: Boolean; var dwDelayTime: LongWord): Boolean;
    procedure ClientSetBagOrder(nItemCount: Integer; sData: string);
    procedure ClientCatchEvil(EvilObject: TBaseObject; nMakeIndex: Integer);
    procedure ClientAddEvilToItem(nWhere: word; nMakeIndex, BottleIndex: Integer);
    procedure ClientAddAntiEvilPower(nWhere: word; nMakeIndex, nAntiEvilItem: Integer);
    function GetEvilRecByMakeIndex(nItemMakeIndex: Integer): pTEvil;
    procedure DelEvilRec(nItemMakeIndex: Integer; DisMem: Boolean = True);
    procedure ClientRequest(wIdent: word; nOp, nOpCode: Integer);
    procedure ClientEvoluTion(wParam: word; nMainMakeIndex, nAuxMakeIndex, nMakeIndex: Integer);
    procedure ClientPetMakeBaby(nMaleMakeIndex, nFemaleMakeIndex: Integer);
    procedure ClientUPGradeTreasureBox(nCount: Integer; sBuf: string);
    procedure ClientEnlargeTreasureBox();
    procedure ClientInjectPowerToTreasureBox(nPoint: Integer);
    procedure ClientActivationTreasureBox();
    procedure ClientTakeItemToTreasureBox(nItemID: Integer);
    procedure ClientTakeItemOutTreasureBox(nItemID: Integer);
    function MagDoBatfly(UserMagic: pTUserMagic; nTargetX, nTargetY: Integer): Boolean;             //化身蝙蝠、移形换影、遁地
    procedure SendPetBagItems;
    procedure HorseHide;
    procedure PetHide(nMakeIndex: Integer);
    procedure SendDelDealItem(UserItem: pTUserItem);
    procedure SendAddDealItem(UserItem: pTUserItem);
    procedure OpenDealDlg(BaseObject: TBaseObject);
    function EatItems(StdItem: pTStdItem): Boolean;
    function EatUseItems(nShape: Integer): Boolean;
    function DayBright(): byte;
    procedure BaseObjectMove(sMAP, sX, sY: string);
    function RepairWeapon(): Boolean;
    function SuperRepairWeapon(): Boolean;
    function SuperRepairUseItems(): Boolean;
    function WinLottery(): Boolean;
    procedure ChangeServerMakeSlave(SalveInfo: pTSlaveInfo);
    function WeaptonMakeLuck(): Boolean;
    function PileStones(nX, nY: Integer): Boolean;
    procedure MakeMine();
    function GetRangeHumanCount(): Integer;
    procedure GetStartPoint();
    procedure MobPlace(sX, sY, sMonName, sCount: string);
    function PetDoShopCanSellCount: Integer;                                                        //计算豹子能摆摊几个物品
    procedure LogonTimcCost;
    procedure QuerySubAbility;
    procedure SendNotice();
    procedure SendLogon();
    function CheckUserItemTimeOut(UserItem: pTUserItem; StdItem: pTStdItem): Boolean;
    function IsGotoLabel(sMapName: string; nX, nY, nRange, nQuestFalgStatus: Integer;
      boQuestFalgStatus: Boolean; sItemName1, sItemName2: string; boNeedGroup: Boolean; nRandomCount: Integer): Boolean;
    procedure StartMapEventOfDropItem(sItemName: string);
    procedure StartMapEventOfPickUpItem(sItemName: string);
    procedure StartMapEventOfMine();
    procedure StartMapEventOfWalk();
    procedure StartMapEventOfRun();
    procedure StartMapEventOfButch();
    {客户端操作}
    function CheckCanOperate(Action: TClientAction; nKey: Integer = 0): Boolean;
    procedure ClientQueryUserName(Target: TBaseObject; X, Y: Integer);
    procedure ClientRequestPetDoShop();                                                             //请求摆摊
    procedure ClientDoShop(shopItemCount: word; sMsg: string);
    procedure ClientPetDoShop(nPet: Integer; shopItemCount: word; sMsg: string);
    procedure ClientGetbackPetShopItem();
    procedure ClientGetbackPetMoney();
    procedure ClientUpdatePetShop(nPet: Integer; nOpCode: Integer; sMsg: string);
    procedure ClientPetStopDoShop();                                                                //宠物收摊
    procedure ClientPersonalSet(Parm1, Parm2, Parm3: Word; sMsg: string);
    procedure ClientStorageItemToPetBag(nItemIdx: Integer);
    procedure ClientOpenHuanjing(nItemIdx: Integer; nOpCode: Integer; nCount: Integer);
    procedure ClientEvilOp(nOpCode: Integer; nEvilMonID: Integer; nMakeIndex: Integer);
    procedure ClientErnie(nOpCode: word);
    procedure ClientTakebackPetItem(nItemIdx: Integer);
    function ClientOpPneumaBagItem(sData: string): Boolean;
    function ClientOpPneumaGold(sData: string): Boolean;
    procedure ClientFelementOrderFlag(nMakeIndex, nMon: Integer);
    procedure ClientReCallGuarder(nMakeIndex, nX, nY: Integer);
    procedure ClientCreateSoul(nParm1, nParm2, nParm3: Integer);
    procedure ClientPhoenixSearch(nPetItem, nParm2: Integer);
    procedure ClientAllotGuildGold(sName: string; nGold: Integer);
    procedure ClientCtrlMental(wOpCode: word);
    procedure ClientTakeOnTigerItem(nWhere, nMakeIndex: Integer);
    procedure ClientTakeOffTigerItem(nWhere, nMakeIndex: Integer);
    procedure ClientTakeOnInosculatePneumaItem(nWhere, nMakeIndex: Integer);
    procedure ClientTakeOffInosculatePneumaItem(nWhere, nMakeIndex: Integer);
    procedure ClientTakeOnPetSoulItem(nWhere, nMakeIndex: Integer; wIndex: word);
    procedure ClientTakeOffPetSoulItem(nWhere, nMakeIndex: Integer; wIndex: word);
    procedure ClientDECOMPOSE(nParam, nMakeIndex: Integer);
    procedure ClientGEMREMOVE(nWhere, nMakeIndex: Integer);
    procedure ClientYiWangDan(nMakeIndex: Integer; sSkillName: string);
    procedure SendUseitems();
    procedure SendUseMagic();
    procedure SendSaveItemList(nBaseObject: Integer; boFast: Boolean);
    procedure SendDelItemList(ItemList: TStringList);
    procedure SendAdjustBonus();
    procedure SendChangeGuildName();
    procedure ShowMapInfo(sMAP, sX, sY: string);
    procedure ReadAllBook;
    function CheckItemsNeed(StdItem: pTStdItem): Boolean;
    function CheckItemBindUse(UserItem: pTUserItem): Boolean;
    function CheckActionStatus(wIdent: word; var dwDelayTime: LongWord): Boolean;
    procedure RecalcAdjusBonus;
    procedure RecalcAdditionalAbil;
    procedure RecalcAddInosculatePneumaAbil;
    procedure RecalcAddProvisionalAbil;
    procedure RecalcAddPetAbil;
    procedure RecalcPetSoulAbilitys;

    procedure CheckMarry();
    procedure CheckMaster();
    procedure ProcessClientPassword(ProcessMsg: pTProcessMessage);
    function CheckDenyLogon: Boolean;
    procedure ProcessSpiritSuite;
    function HorseRunTo(btDir: byte; boFlag: Boolean): Boolean;
    procedure SendTaskList;
    procedure ClientQueryBaoshi;
    procedure ClientSendBlessMsg(NPC: Integer; MsgFlag: Integer; sMsg: string);
    procedure ClientGemSmelt(nState: Integer; RedBaoshi, BlueBaoshi, GreenBaoshi: Integer; sItems: string);
    procedure ClientGemItems(NPC: Integer; nType: Integer; nItemCount: Integer; nState: Integer; sData: string);
    procedure ClientRefineItems(nType: Integer; nItemIdx, nItemIdx2: Integer; sData: string);
    procedure ClientOriginalStoneSmelt(nItemIdx, nType, nState: Integer; sData: string);
    procedure ClientEntopticSmelt(nState: Integer; sData: string);
    procedure ClientfuseequipItem(nState: Integer; nItemIdx, nItemIdx2: Integer; sData: string);
    procedure ChangePneumaState;
    procedure MakeFlagOwner(nflagType: Integer; ItemIdx: Integer; nX, nY: Integer; sData: string);
    procedure AddFlagComment(nflagType: Integer; NPCID: Integer; nMsgLen: Integer; sMsg: string);
    procedure ClickQueryMsg(NPCID: Integer; btnid: Integer);
    procedure GetTreasureBoxItem(wParam: word; nParam1, nParam2, nParam3: Integer; sMsg: string);
    procedure SendNearbyGuildMemberList();
    procedure ClientAskForGuildOfficial(nRankNo: Integer; sData: string);
    procedure ClientGuildOfficial(nCode, nRankNo: Integer; sChiefName: string);
    procedure SendTreasurePavilion();
    procedure SendNonSuchPavilion(nSerial: Integer);
    procedure ClientCallTiger();
    procedure ClientSetTigerTarget(nMonID, nOp, nX, nY: Integer);
    procedure ClientQueryMapLotusInfo();
    function ClientTakeOnEntopticItems(btWhere: byte; nItemIdx: Integer): Boolean;                  //装备元神内视装备
    function ClientTakeOffEntopticItems(btWhere: byte; nItemIdx: Integer): Boolean;                 //取下元神内视装备
    function ClientIllumeHeartPoint(btWhere, btPlace: byte): Boolean;                               //点亮心命点
    procedure SendHeartFatePoint();
    procedure SendEntopticItems();
    procedure ClientQueryGuildClanList();
    procedure ClientClanOperate(nOpCode: Integer; sMsg: string);
    procedure ClientClanReQuery(nOpCode: Integer; sMsg: string);
    procedure MagFieryDragonRun();
    procedure ClientCatapultAttackTarget(nOpCode, nX, nY: Integer);
    procedure ClientQueryPetSoulInfo;                                                               //发送魂佑灵兽信息
    procedure ClientQueryPetSoulItem(nMakeIndex: Integer; wIndex: word);                            //查询魂佑灵兽装备
    procedure ClientMagOfPetBeast(nMakeIndex: Integer);
    procedure ClientCheckVerifyCode(sVerifyCode: string; boOutTime: Boolean = False);
    procedure ClientQueryAbility();
  protected
    procedure RecalcAbilitysEx(); override;
  public
    m_boInNonSuchPavilion: Boolean;
    procedure CheckPackPetShop();
    procedure ClientClickNPC(NPC: Integer);
    procedure SendMapDescription();
    procedure SendBagItemsPetInfo();
    procedure SendPetAttribute(PlayObject: TPlayObject; btWhere: byte; UserItem: pTUserItem);       //发送灵兽石附加属性
    procedure SendAddPetSoulInfo(nMakeIndex: Integer);
    procedure SendGuildTowerInfo();
    procedure SendGuildTowerRes();
    procedure RecalcTowerAbility();
    procedure SendTigerInfo();
    procedure RecalcTigerLevelAbilitys;
    procedure RecalcTigerAbility();
    procedure TigerDefendMaster(var nDamage: Integer);
    procedure TigerTransferDamage(var nDamage: Integer);
    procedure SlaveTransferDamage(var nDamage: Integer);
    procedure BaoBaoTransferDamage(var nDamage: Integer);                                           //宝宝斗转
    procedure PneumaLogin;
    procedure PetShow(nMakeIndex: Integer);
    function CancelGroup(): Boolean;
    procedure ClientQueryTreasureBoxItems(const boSend: Boolean = True);
    procedure ClientReCallTiger();
    procedure ClientSwitchPneuma();
    procedure ClientInosculatePneuma();
    procedure ClientQueryMentalAbilitys(PlayObject: TPlayObject);
    procedure ClientBuyShopItem(Play: TBaseObject; sItemName: string; nInt: Integer);
    procedure RecalcMentalLevelAbilitys;
    procedure SendWenPeiJH();                                                                       //发送纹佩精华
    procedure ClientAchievementSystem(boWenPei: Boolean = False);                                   //成就系统

    procedure RecalcPerHealthSpell(); override;
    procedure ClientMakeWenPei(btZW, btJW, btDW, btBW: byte);                                       //制做纹佩
    procedure ClientGetWenPeiDemand(nMakeIndex, nCode: Integer);
    procedure ClientTakeWenPei(nMakeIndex, nCode: Integer);                                         //强化 或 拆解 纹佩
    procedure ClientCollectSuits(nCJIdx, nCount: Integer; sData: string);                           //成就之收集套装
    procedure ClientPetEquipUp(nPetItemIdx, nStoreItemIdx: Integer; sData: string);                 //升级灵兽装备
    function TrainingPetSkill(const StdItem: pTStdItem): Boolean;                                   //学习灵兽抵抗技能
    procedure RecalcAddSuiteAbil(Idx: Integer; boPercent: Boolean);
  public
    constructor Create(); override;
    destructor Destroy; override;
    procedure ClearUp(btFree: Boolean = False); override;
    procedure SendSocket(DefMsg: pTDefaultMessage; sMsg: string); override;
    procedure SendDefMessage(wIdent: word; nRecog: Integer; nParam, nTag, nSeries: word; sMsg: string; boEn: Boolean = False); override;
    procedure SendFiendList(const b: ShortInt = -1);
    procedure SearchViewRange(); override;
    procedure OnEnvirnomentChanged(OldEnvir: TEnvirnoment; boChanged: Boolean = True); override;
    procedure PKDie(PlayObject: TPlayObject);
    procedure CreatePneumaEnd(btFlag: Integer; sNewName: string; nSex, btHumKind: byte);
    procedure GameTimeChanged();
    procedure RunNotice();
    //AI动作
    function gotopoint(smapName: string;nx,ny:integer): Boolean;
    function WalkToNext(nX, nY: Integer): Boolean;
    function RunToNext(nX, nY: Integer): Boolean;
        procedure Stop;
function GetBagItemCount(sItemName: string): Integer;
function Think(): Boolean;
procedure GotoTargetXYRange();
function GotoNextOne(nX, nY: Integer; boRun: Boolean): Boolean;
    function GetMagicSpell(UserMagic: pTUserMagic): Integer;
procedure Attack(TargeTBaseObject: TBaseObject; nDir: Integer); overload;
function actAttackTarget(): Boolean;
procedure GotoTargetXY;
procedure SetTargetXY(nX, nY: Integer); virtual;                                                //FFF0
function CheckTargetXYCount(nX, nY, nRange: Integer): Integer;
function CheckTargetXYCountOfDirection(nX, nY, nDir, nRange: Integer): Integer;
function AutoAvoid(): Boolean;
function canatackTarget(BaseObject:TBaseObject): Boolean;
procedure UpdatenoatcktActors(BaseObject: TBaseObject);
     procedure Wondering();
    procedure SearchTarget;
    function GetMyStatus(): Integer;
    procedure MoveToHome();
    procedure MoveToHomeRandom();
    procedure SendAddMagic(UserMagic: pTUserMagic);
    procedure SendDelMagic(UserMagic: pTUserMagic);
    procedure SendAddItem(UserItem: pTUserItem); override;
    procedure SendAddPetItem(UserItem: pTUserItem);
    procedure SendDelItems(UserItem: pTUserItem); override;
    procedure Whisper(whostr, saystr: string; nType: Integer = 1);
    function ClientPickUpItem(nX, nY, nType: Integer): Boolean;
    function IsBlockWhisper(sName: string): Boolean;
    function QuestCheckItem(sItemName: string; var nCount: Integer; var nParam:
      Integer; var nDura: Integer): pTUserItem;
    function QuestCheckItemEx(sItemName: string; nDura: Integer; boParam: Boolean): Integer;
    function QuestCheckItemX(sItemName: string; var nCount: Integer; var nParam:
      Integer; var nDura: Integer): pTUserItem;
    function GetCheckItemValue(nMakeIndex: Integer; sName: string): string;
    function GetItemValueSum(sItemName: string; sValName: string): Integer;
    function GetItemCountWithValue(sItemName: string; sValName: string; nValue: Integer): Integer;
    function QuestTakeCheckItem(CheckItem: pTUserItem): Boolean;
    procedure GainExp(dwExp: LongWord; dwMilitaryExp: LongWord; dwRepressDemonExp: LongWord);
    function GetExploit(PlayObject: TBaseObject): Boolean;
    function GetBeadExp(): Boolean;
    function GetWingExp(): Boolean;
    procedure GetExp(nExp: UInt64; nMilitaryExp: UInt64; nRepressDemon: UInt64; bScritpExp: Boolean = False; boShareMilitaryExp: Boolean = False; boShareRepressDemon: Boolean = False);
    procedure GetExpProc(nGetExp: UInt64; nGetMilitaryExp: UInt64; nGetRepressDemonExP: UInt64; bScritpExp: Boolean = False);
    procedure WinExp(nExp: UInt64; nMilitaryExp: UInt64; nRepressDemonExp: UInt64);
    procedure ClientGuildMemberList();
    procedure Run(); override;
    function Operate(ProcessMsg: pTProcessMessage): Boolean; override;
    procedure SendStruckMsg(wIdent: word; BaseObject, Attacker: TBaseObject; nDamage: Integer; wEffect: word);
    procedure RecalcAbilitys(boAction: Boolean = False); override;

    procedure DealCancel();
    procedure DealCancelA();
    function GetShowName(): string; override;
    procedure GetBackDealItems();
    procedure Disappear(); override;
    procedure GoldChange(sChrName: string; nGold: Integer);
    procedure ProcessUserLineMsg(sData: string; MsgType: word);
    procedure ProcessSayMsg(sData: string; nMsgType: Integer); override;
    procedure ClearStatusTime();
    procedure UserLogon(); virtual;
    procedure RefRankInfo(nRankNo: Integer; sRankName: string);
    procedure RefUserState;
    procedure SendGroupMembers();
    procedure JoinGroup(PlayObject: TPlayObject);
    function GeTBaseObjectInfo(): string;
    function GetHitMsgCount(): Integer;
    function GetSpellMsgCount(): Integer;
    function GetWalkMsgCount(): Integer;
    function GetRunMsgCount(): Integer;
    function GetTurnMsgCount(): Integer;
    function GetSiteDownMsgCount(): Integer;
    function GetDigUpMsgCount(): Integer;
    procedure SetScriptLabel(sLabel: string);
    procedure GetScriptLabel(sMsg: string; boLeft: Boolean);
    procedure SendScriptItemPic(sMsg: string; nParam: Integer);
    function LableIsCanJmp(sLabel: string; boLeft: Boolean): Boolean;
    function GetMyInfo(): string;
    procedure MakeGhost; override;
    procedure ScatterBagItems(ItemOfCreat: TBaseObject); override;
    procedure DropUseItems(BaseObject: TBaseObject; AttackBaseObject: TBaseObject = nil); override;
    function RecallHuman(sHumName: string; wRecallType: word): Boolean;
    procedure CancelDoShop;
    procedure UPGRADEMON(nType: Integer);
    procedure ReQuestGuildWar(sGuildName: string; WarTime: Integer = 0);
    procedure SendUpdateItem(UserItem: pTUserItem; boDelay: Boolean = True); override;
    procedure AddEvilToItemB(nWhere: word; nMakeIndex, BottleIndex: Integer);
    procedure ReleaseEvil(nMakeIndex: Integer);
    procedure GetBagUseItems(var btDc: byte; var btSc: byte; var btMc: byte; var btDura: byte);
    procedure CmdEndGuild();
    procedure CmdMemberFunction(sCmd, sParam: string);
    procedure CmdMemberFunctionEx(sCmd, sParam: string);
    procedure CmdSearchDear(sCmd, sParam: string);
    procedure CmdSearchMaster(sCmd, sParam: string);
    procedure CmdDearRecall(sCmd, sParam: string);
    procedure CmdMasterRecall(sCmd, sParam: string);
    procedure CmdFriendRecall(sCmd, sParam: string);
    procedure CmdSbkDoorControl(sCmd, sParam: string);
    procedure CmdClearBagItem(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdShowUseItemInfo(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdBindUseItem(Cmd: pTGameCmd; sHumanName, sItem, sType: string);
    procedure CmdUnBindUseItem(Cmd: pTGameCmd; sHumanName, sItem, sType: string);
    procedure CmdLockLogin(Cmd: pTGameCmd);
    procedure CmdViewDiary(sCmd: string; nFlag: Integer);
    procedure CmdUserMoveXY(sCmd, sX, sY: string);
    procedure CmdSearchHuman(sCmd, sHumanName: string);
    procedure CmdGroupRecall(sCmd: string; AllRecall: Boolean = False);
    procedure CmdAllowGroupReCall(sCmd, sParam: string);
    procedure CmdGuildRecall(sCmd, sParam: string);
    procedure CmdChangeAttackMode(nMode: Integer);
    procedure CmdChangeSalveStatus();
    procedure CmdChangeTigerStatus;
    procedure CmdTakeOnHorse(sCmd, sParam: string);
    procedure CmdTakeOffHorse(sCmd, sParam: string);
    procedure CmdPrvMsg(sCmd: string; nPermission: Integer; sHumanName: string);
    procedure CmdHumanLocal(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdMapMove(Cmd: pTGameCmd; sMapName: string);
    procedure CmdPositionMove(Cmd: pTGameCmd; sMapName, sX, sY: string);
    procedure CmdHumanInfo(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdReLoadAdmin(sCmd: string);
    procedure CmdReloadNpc(sParam: string);
    procedure CmdReloadManage(Cmd: pTGameCmd; sParam: string);
    procedure CmdReloadRobotManage;
    procedure CmdReloadRobot;
    procedure CmdReloadMonItems();
    procedure CmdAdjustExp(human: TPlayObject; nExp: Integer);
    procedure CmdAddGuild(Cmd: pTGameCmd; sGuildName, sGuildChief: string);
    procedure CmdDelGuild(Cmd: pTGameCmd; sGuildName: string);
    procedure CmdGuildWar(sCmd, sGuildName: string);
    procedure CmdChangeSabukLord(Cmd: pTGameCmd; sCASTLENAME, sGuildName: string; boFlag: Boolean);
    procedure CmdForcedWallconquestWar(Cmd: pTGameCmd; sCASTLENAME: string);
    procedure CmdOPTraining(sHumanName, sSkillName: string; nLevel: Integer);
    procedure CmdOPDeleteSkill(sHumanName, sSkillName: string);
    procedure CmdReloadGuildAll();
    procedure CmdReAlive(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdAdjuestLevel(Cmd: pTGameCmd; sHumanName: string; nLevel: Integer);
    procedure CmdAdjuestExp(Cmd: pTGameCmd; sHumanName, sExp: string);
    procedure CmdBackStep(sCmd: string; nType, nCount: Integer);
    procedure CmdFreePenalty(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdPKpoint(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdIncPkPoint(Cmd: pTGameCmd; sHumanName: string; nPoint: Integer);
    procedure CmdHunger(sCmd, sHumanName: string; nHungerPoint: Integer);
    procedure CmdHair(Cmd: pTGameCmd; sHumanName: string; nHair: Integer);
    procedure CmdTrainingSkill(Cmd: pTGameCmd; sHumanName, sSkillName: string; nLevel: Integer);
    procedure CmdTrainingMagic(Cmd: pTGameCmd; sHumanName, sSkillName: string; nLevel: Integer);
    procedure CmdDelSkill(Cmd: pTGameCmd; sHumanName, sSkillName: string);
    procedure CmdDeleteItem(Cmd: pTGameCmd; sHumanName, sItemName: string; nCount: Integer);
    procedure CmdClearMission(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdTraining(sSkillName: string; nLevel: Integer);
    procedure CmdChangeJob(Cmd: pTGameCmd; sHumanName, sJobName: string);
    procedure CmdChangeGender(Cmd: pTGameCmd; sHumanName, sSex: string);
    procedure CmdMission(Cmd: pTGameCmd; sX, sY: string);
    procedure CmdMobPlace(Cmd: pTGameCmd; sX, sY, sMonName, sCount: string);
    procedure CmdMobLevel(Cmd: pTGameCmd; Param: string);
    procedure CmdMobCount(Cmd: pTGameCmd; sMapName: string);
    procedure CmdHumanCount(Cmd: pTGameCmd; sMapName: string);
    procedure CmdDisableFilter(sCmd, sParam1: string);
    procedure CmdChangeUserFull(sCmd, sUserCount: string);
    procedure CmdChangeZenFastStep(sCmd, sFastStep: string);
    procedure CmdReconnection(sCmd, sIPaddr, sPort: string);
    procedure CmdContestPoint(Cmd: pTGameCmd; sGuildName: string);
    procedure CmdStartContest(Cmd: pTGameCmd; sParam1: string);
    procedure CmdEndContest(Cmd: pTGameCmd; sParam1: string);
    procedure CmdAnnouncement(Cmd: pTGameCmd; sGuildName: string);
    procedure CmdKill(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdMakeItem(Cmd: pTGameCmd; sItemName: string; nCount: Integer);
    procedure CmdSmakeItem(Cmd: pTGameCmd; nWhere, nValueType: Integer; sOpCode: string; nValue: Integer);
    procedure CmdBonuPoint(Cmd: pTGameCmd; sHumName: string; nCount: Integer);
    procedure CmdDelBonuPoint(Cmd: pTGameCmd; sHumName: string);
    procedure CmdRestBonuPoint(Cmd: pTGameCmd; sHumName: string);
    procedure CmdFireBurn(nInt, nTime, nn: Integer);
    procedure CmdTestFire(sCmd: string; nRange, nType, nTime, nPoint: Integer);
    procedure CmdTestStatus(sCmd: string; nType, nTime: Integer);
    procedure CmdDelGold(Cmd: pTGameCmd; sHumName: string; nCount: Integer);
    procedure CmdAddGold(Cmd: pTGameCmd; sHumName: string; nCount: Integer);
    procedure CmdGameGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
    procedure CmdGamePoint(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nPoint: Integer);
    procedure CmdBindGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
    procedure CmdBindGameGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
    procedure CmdCreditPoint(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nPoint: Integer);
    procedure CmdMob(Cmd: pTGameCmd; sMonName: string; nCount, nLevel: Integer; sShowName: string);
    procedure CmdRefineWeapon(Cmd: pTGameCmd; nDc, nMc, nSc, nHit: Integer);
    procedure CmdRecallMob(Cmd: pTGameCmd; sMonName: string; nCount, nLevel, nAutoChangeColor, nFixColor: Integer);
    procedure CmdLuckPoint(sCmd: string; nPermission: Integer; sHumanName, sCtr, sPoint: string);
    procedure CmdLotteryTicket(sCmd: string; nPermission: Integer; sParam1: string);
    procedure CmdReloadGuild(sCmd: string; nPermission: Integer; sParam1: string);
    procedure CmdReloadLineNotice(sCmd: string; nPermission: Integer; sParam1: string);
    procedure CmdReloadAbuse(sCmd: string; nPermission: Integer; sParam1: string);
    procedure CmdMobNpc(sCmd: string; nPermission: Integer; sParam1, sParam2, sParam3, sParam4: string);
    procedure CmdNpcScript(sCmd: string; nPermission: Integer; sParam1, sParam2, sParam3: string);
    procedure CmdDelNpc(sCmd: string; nPermission: Integer; sParam1: string);
    procedure CmdKickHuman(Cmd: pTGameCmd; sHumName: string);
    procedure CmdTing(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdSuperTing(Cmd: pTGameCmd; sHumanName, sRange: string);
    procedure CmdMapMoveHuman(Cmd: pTGameCmd; sSrcMap, sDenMap: string);
    procedure CmdShutup(Cmd: pTGameCmd; sHumanName, sTime: string);
    procedure CmdShowMapInfo(Cmd: pTGameCmd; sParam1: string);
    procedure CmdShutupRelease(Cmd: pTGameCmd; sHumanName: string; boAll: Boolean);
    procedure CmdShutupList(Cmd: pTGameCmd; sParam1: string);
    procedure CmdShowSbkGold(Cmd: pTGameCmd; sCASTLENAME, sCtr, sGold: string);
    procedure CmdRecallHuman(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdReGotoHuman(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdShowHumanFlag(sCmd: string; nPermission: Integer; sHumanName, sFlag: string);
    procedure CmdShowHumanUnitOpen(sCmd: string; nPermission: Integer; sHumanName, sUnit: string);
    procedure CmdShowHumanUnit(sCmd: string; nPermission: Integer; sHumanName, sUnit: string);
    procedure CmdChangeAdminMode(sCmd: string; nPermission: Integer; sParam1: string; boFlag: Boolean);
    procedure CmdChangeObMode(sCmd: string; nPermission: Integer; sParam1: string; boFlag: Boolean);
    procedure CmdChangeSuperManMode(sCmd: string; nPermission: Integer; sParam1: string; boFlag: Boolean);
    procedure CmdChangeLevel(Cmd: pTGameCmd; sParam1: string);
    procedure CmdChangeDearName(Cmd: pTGameCmd; sHumanName: string; sDearName: string);
    procedure CmdChangeMasterName(Cmd: pTGameCmd; sHumanName: string; sMasterName, sIsMaster: string);
    procedure ChangeMasterName(sHumanName, sMasterName: string; boMaster: Boolean);
    procedure CmdStartQuest(Cmd: pTGameCmd; sQuestName, sMapName: string);
    procedure CmdSetPermission(Cmd: pTGameCmd; sHumanName, sPermission: string);
    procedure CmdClearMapMonster(Cmd: pTGameCmd; sMapName, sMonName, sItems, sGhost: string);
    procedure CmdReNewLevel(Cmd: pTGameCmd; sHumanName, sLevel: string);
    procedure CmdDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr, sFixDeny: string);
    procedure CmdDelDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr, sFixDeny: string);
    procedure CmdShowDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr, sFixDeny: string);
    procedure CmdDenyAccountLogon(Cmd: pTGameCmd; sAccount, sFixDeny: string);
    procedure CmdDelDenyAccountLogon(Cmd: pTGameCmd; sAccount, sFixDeny: string);
    procedure CmdShowDenyAccountLogon(Cmd: pTGameCmd; sAccount, sFixDeny: string);
    procedure CmdDenyCharNameLogon(Cmd: pTGameCmd; sCharName, sFixDeny: string);
    procedure CmdDelDenyCharNameLogon(Cmd: pTGameCmd; sCharName, sFixDeny: string);
    procedure CmdShowDenyCharNameLogon(Cmd: pTGameCmd; sCharName, sFixDeny: string);
    procedure CmdViewWhisper(Cmd: pTGameCmd; sCharName, sParam2: string);
    procedure CmdSpirtStart(sCmd: string; sParam1: string);
    procedure CmdSpirtStop(sCmd: string; sParam1: string);
    procedure CmdSetMapMode(sCmd: string; sMapName, sMapMode, sParam1, sParam2: string);
    procedure CmdShowMapMode(sCmd: string; sMapName: string);
    procedure CmdClearHumanPassword(sCmd: string; nPermission: Integer; sHumanName: string);
    procedure CmdChangeItemName(sCmd, sMakeIndex, sItemIndex, sItemName: string);
    procedure CmdDisableSendMsg(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdEnableSendMsg(Cmd: pTGameCmd; sHumanName: string);
    procedure CmdDisableSendMsgList(Cmd: pTGameCmd);
    procedure CmdTestGetBagItems(Cmd: pTGameCmd; sParam: string);
    procedure CmdMobFireBurn(Cmd: pTGameCmd; sMAP, sX, sY, sType, sTime, sPoint: string);
    procedure CmdTestSpeedMode(Cmd: pTGameCmd; nWhere, nType: Integer);
    function ProcessUserCmd(sCmd, sParam1, sParam2, sParam3, sParam4, sParam5, sParam6, sParam7: string): Boolean;
    function ExecuteScript(ScriptObj: TObject; sLabel: string): Boolean; override;

    function GetTaskVal(const TaskID: Integer; ValID: Integer): Integer;
    function GetTaskStr(const TaskID: Integer; ValID: Integer): string;
    function GetColorTaskCount(): Integer;
    function GetTaskStep(const TaskID: Integer): Integer;
    function UpdateTaskStep(const TaskID: Integer; nStep: Integer): Integer;
    procedure RefreshTask(const TaskID, nStep: Integer);
    procedure SendColorTask(const TaskID, Color: Integer);
    procedure ClientDelTask(const TaskID: Integer);
    procedure ClientQueryEvilFollower;
    procedure ClearEvilFollower(nCode: Integer);
    function CheckMapRideOn(Envir: TEnvirnoment): Boolean;
    procedure DelPneuma(nIdx: Integer);
    procedure DelPneumaEnd(nIdx, btSex, btCount: byte);
    procedure TakeItemOn(sItemName: string; btWhere: Integer);
    procedure SendMagic_LvExp_Msg(const UserMagic: pTUserMagic; dwDelay: LongWord); override;
    procedure SendShopItems(BaseObject: TBaseObject; opcode: word); override;
    procedure SendShopResult(); override;
    function IsShop(): Boolean; override;                                                           //是否摆摊
    procedure GetUserShop(const pUserShop: PTUserShop); override;                                   //取摆摊状态
    function GetPetSoulItem(const nMakeIndex: Integer; boNew: Boolean = False): pTPetSoulItem;      //取一个魂佑装备位

    function GetAchievementInfo(const wIndex: word): PTAchievementInfo;
    procedure SendBroadVehicle(btCreatorType: Byte; VehicleExp: TVehicleExp);

    procedure SendWishAwardInfo();
  published
    property m_nPetShopSize: Integer read PetDoShopCanSellCount;
  end;

implementation
uses
  Math, WolShare, Guild, HUtil32, ObjNpc, IdSrvClient, ItmUnit, Event, ObjMon, RandomEngine,  aiplayer,
  LocalDB, Castle, svMain, Magic, ObjMon3, ObjGoblin, EnvirMirror;

{ TPlayObject }

constructor TPlayObject.Create;                                                                     //004C9860
begin
  inherited;
  m_DelayCall := TList.Create;
  m_MasterList := TList.Create;
  //跑位魔法间隔
  m_DynamicVarList := TList.Create;
  m_ArrowList := TStringList.Create;
  m_PetSoulItemsList := TList.Create;
  m_CustomTableList := TList.Create;
  m_AchievementList := TList.Create;
  m_KnockEggList := TList.Create;
  m_CheckCondition := TList.Create;
end;

destructor TPlayObject.Destroy;                                                                     //004C9B54
var
  i, nCheckCode                         : Integer;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::Destroy Code:=%d';
begin
  nCheckCode := 0;
  try
    //清空
    ClearFree;
    nCheckCode := 1;
    m_MasterList.free;
    nCheckCode := 2;
    m_DynamicVarList.free;
    nCheckCode := 3;
    m_DelayCall.free;
    nCheckCode := 4;
    m_ArrowList.free;
    m_PetSoulItemsList.free;
    FreeAndNil(m_CustomTableList);
    FreeAndNil(m_AchievementList);
    FreeAndNil(m_KnockEggList);
    FreeAndNil(m_CheckCondition);
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
  inherited;
end;

procedure TPlayObject.ClearUp(btFree: Boolean = False);
begin
  inherited ClearUp(btFree);
  m_btRaceServer := RC_PLAYOBJECT;
  m_boEmergencyClose := False;
  m_boSwitchData := False;
  m_boReconnection := False;
  m_boKickUserSessInfo := False;
  m_boBagSend := False;
  m_boKickFlag := False;
  m_boSoftClose := False;
  m_boReadyRun := False;
  //  bo698 := False;
  m_dwHuanjingTick := GetTickCount;
  m_nAnserIdx := -1;
  //  n69C := 0;
  m_nHuanjingIdx := 0;
  m_dwSaveRcdTick := GetTickCount();
  m_boWantRefMsg := True;
  m_boRcdSaved := False;
  m_boDieInFight3Zone := False;

  m_boTimeRecall := False;
  m_sMoveMap := '';
  m_nMoveX := 0;
  m_nMoveY := 0;
  m_dwRunTick := 0;                                                                                 //最后处理人物消息时间
  m_nRunTime := 100;                                                                                //处理人物消息间隔    延时设置
  m_dwSearchTime := 1000;
  m_dwSearchTick := 0;
  m_nViewRange := 12;
  m_boNewHuman := False;
  m_boLoginNoticeOK := False;
  //  bo6AB := False;
  m_boSendNotice := False;

  m_boRideOn := False;
  m_boRideFightOn := False;
  m_btHorseType := 0;
  m_Horse := nil;
  m_Pet := nil;
  m_PackPet := nil;
  FillChar(m_PetInfo, SizeOf(m_PetInfo), #0);
  m_dwPneumaChangeTick := 0;
  m_dwDoMotaeboMoveTick := GetTickCount();
  m_dwEatTalismanTick := 0;
  m_dwCheckDupObjTick := GetTickCount();
  dwTick578 := GetTickCount();
  m_boInSafeArea := False;
  m_boInSafezone := False;
  m_dwCheckSafeArea := GetTickCount();
  m_dwMagicAttackTick := GetTickCount();
  m_dwMagicAttackInterval := 0;
  m_dwAttackTick := GetTickCount();
  m_dwMoveTick := GetTickCount();
  m_dwTurnTick := GetTickCount();
  m_dwActionTick := GetTickCount();
  m_dwAttackCount := 0;
  m_dwAttackCountA := 0;
  m_dwMagicAttackCount := 0;
  m_dwMoveCount := 0;
  m_dwMoveCountA := 0;
  m_nOverSpeedCount := 0;
  m_sOldSayMsg := '';
  m_dwSayMsgTick := 0;
  m_boDisableSayMsg := False;
  m_dwDisableSayMsgTick := GetTickCount();

  //  n584 := 0;
  //  n588 := 0;
  m_boSwitchData := False;
  m_boSwitchDataSended := False;
  m_nWriteChgDataErrCount := 0;
  m_dwShowLineNoticeTick := GetTickCount();
  m_nShowLineNoticeIdx := 0;
  m_sMasterName[1] := '';
  m_sMasterName[2] := '';
  m_sMasterName[3] := '';
  m_nKillMonExpRate := 100;
  m_wKillMonExpRate := 100;
  m_dwKillMonBurstRateTime := 0;
  m_dwKillMonExpRateTime := 0;
  m_dwRateTick := GetTickCount();
  m_dwDecAntvPowerTick := GetTickCount();
  m_nPowerRate := 100;
  m_dwPowerRateTime := 0;
  m_nDefenceRate := 100;
  m_dwDefenceRateTime := 0;
  m_boSetStoragePwd := False;
  m_boReConfigPwd := False;
  m_boCheckOldPwd := False;
  m_boUnLockPwd := False;
  m_boUnLockStoragePwd := False;
  m_boPasswordLocked := False;                                                                      //锁仓库
  m_btPwdFailCount := 0;
  m_sTempPwd := '';
  m_sStoragePwd := '';

  m_boFilterSendMsg := False;
  m_DearHuman := nil;
  m_MasterHuman := nil;

  m_sStoreName := '';
  m_nStoreMakeIndex := 0;
  m_boCanMasterRecall := False;
  m_boCanDearRecall := False;
  m_dwDearRecallTick := GetTickCount();
  m_dwMasterRecallTick := GetTickCount();
  m_btReColorIdx := 0;
  m_GetWhisperHuman := nil;
  m_wContribution := 0;
  m_sRankLevelName := g_sRankLevelName;

  m_boFixedHideMode := True;
  m_boFilterSendMsg := False;
  m_boCanDeal := False;
  m_boCanDrop := False;
  m_boCanGetBackItem := False;
  m_boCanWalk := False;
  m_boCanRun := False;
  m_boCanHit := False;
  m_boCanSpell := False;
  m_boCanUseItem := False;

  m_nClientFlagMode := -1;
  m_dwAutoGetExpTick := GetTickCount;
  m_nAutoGetExpPoint := 0;
  m_AutoGetExpEnvir := nil;
  m_dwHitIntervalTime := g_Config.dwHitIntervalTime;                                                //攻击间隔
  m_dwMagicHitIntervalTime := g_Config.dwMagicHitIntervalTime;                                      //魔法间隔
  m_dwRunIntervalTime := g_Config.dwRunIntervalTime;                                                //走路间隔
  m_dwWalkIntervalTime := g_Config.dwWalkIntervalTime;                                              //走路间隔
  m_dwTurnIntervalTime := g_Config.dwTurnIntervalTime;                                              //换方向间隔
  m_dwActionIntervalTime := g_Config.dwActionIntervalTime;                                          //组合操作间隔
  m_dwRunLongHitIntervalTime := g_Config.dwRunLongHitIntervalTime;
  //组合操作间隔
  m_dwRunHitIntervalTime := g_Config.dwRunHitIntervalTime;                                          //组合操作间隔
  m_dwWalkHitIntervalTime := g_Config.dwWalkHitIntervalTime;                                        //组合操作间隔
  m_dwRunMagicIntervalTime := g_Config.dwRunMagicIntervalTime;
  m_SessInfo := nil;
  m_boTestSpeedMode := False;
  m_boLockLogon := True;
  m_boLockLogoned := False;

  m_dwLastPersonalSetTick := GetTickCount - 60000;
  m_dwLastRide := GetTickCount() - 3000;
  m_dwWalkTick := 0;
  m_boStickMode := False;
  m_nMaxTaskCount := 10;                                                                            //最大任务总数
  m_nAchievement := 0;                                                                              //活动任务
  m_nTotalTaskCount := 0;                                                                           //总任务数
  m_dwLastBuyShopitemTick := 0;
  m_dwNextBannerNoticeTime := GetTickCount;
  m_nBannerNoticeIdx := 0;
  m_boHideBannerNotice := False;
  m_boOfflineGetGamePoint := False;
  m_boOfflineResume := False;
  m_dwUseStoreTick := 0;
  m_wGemCount[0] := 0;
  m_wGemCount[1] := 0;
  m_wGemCount[2] := 0;
  m_wGemCount[3] := 0;
  m_wGemCount[4] := 0;                                                                              //红宝石、蓝宝石、绿宝石数量
  m_nRefinePoint := 0;
  m_nSpotDlgMode := 0;
  m_nPetTargetX := -1;
  m_nPetTargetY := -1;
  m_sOffLineLabel := '';
  m_nRunCount := 0;
  m_FirstRunTick := GetTickCount;
  m_sHorseName := '';
  m_btSetHorseType := 0;
  m_dwCallPneumaTick := 0;

  m_nEatItemMakeIndex := 0;
  m_nRandomGiveStep := 0;
  m_nAutoOpenTreasureBox := 0;

  m_dwTimerTick := 0;
  m_dwTimerLong := 0;
  m_sTimerLabel := '';

  m_boSafeZoneOnLine := False;
  m_boSaveKillMonExpRate := False;

  m_btLastOutStatus := 0;
  m_sLastMapName := '';
  m_nLastCurrX := 0;
  m_nLastCurrY := 0;
  FillChar(m_Dan, SizeOf(TSoulBabyORDemonDanInfo), #0);
  FillChar(m_ProvisionalAbil, SizeOf(TProvisionalAbil), #0);

  FillChar(m_dwTimer, SizeOf(m_dwTimer), #0);
  m_dwRideFightSkillTick := 0;
  m_boInNonSuchPavilion := False;
  m_wTotemStatus := 0;

  m_boNeedKneel := False;
  m_btRulerLevel := 0;
  m_boCtrlMental := False;

  m_Tiger := nil;
  FillChar(m_TorDDM, SizeOf(TTigerORDemonDanMagic), #0);

  m_boCreatePneuma := False;
  m_pSwitchPneuma := nil;
  m_nPneumaLastX := -1;
  m_boInosculatePneuma := False;
  m_dwInosculateTick := GetTickCount;
  m_wCurFightValue := 0;                                                                            //当前元神战斗值
  m_wInnerPneumaLevel := 0;                                                                         //内部元神战斗值
  m_InosculatePneumaHP := 0;
  m_InosculatePneumaMP := 0;
  m_dwFieryDragonRunTick := 0;
  m_sQueryName := '';
  m_dwEatItemTick := 0;
  m_dwEatDurgHPTick := 0;
  m_dwEatDurgMPTick := 0;
  m_boUnWater := False;
  m_boQueryReLive := False;
  FillChar(m_CustomValue, SizeOf(TCustomValue), #0);
  FillChar(m_LimitValue, SizeOf(TLimitValue), #0);

  m_boCatapultMode := False;
  m_boCatapultAttackMode := False;
  m_dwCatapultAttackTick := GetTickCount;
  m_wCatapultHP := 0;
  m_wCatapultMaxHP := 0;

  FillChar(m_Shop, SizeOf(TShop), #0);
  m_wShopItemCount := 0;
  m_wShopKind := 0;
  m_btShopBanner := 0;
  m_nBannerColor := 0;
  m_sMachineid := '';
  m_btStorageSize := 39;

  m_VersionManage := nil;                                                                           //客户端版本API控制
  FillChar(m_SpiritInfo, SizeOf(TSpiritInfo), #0);                                                  //神魂融合信息


  m_nAllIncReply := 0;

  m_boBeast := False;
  FillChar(m_ReduceSkillLevel, SizeOf(m_ReduceSkillLevel), #0);
  FillChar(m_ReduceSkillPoint, SizeOf(m_ReduceSkillPoint), #0);
  m_ReduceSkillRate := 0;
  m_FelementReduce := 0;
  m_FelementRedouble := 0;
  m_dwWenPeiJH := 0;                                                                                //纹佩精华
  FillChar(m_WenPeiBox, SizeOf(TWenPeiBox), 0);                                                     //纹佩宝盒
  m_wAchievePoint := 0;
  m_nGatherExp := 0;
  m_dwGatherExpTick := GetTickCount();
  m_wPrenticeCount := 0;
  m_boRideDragonMode := False;
  m_dwTotalDamage := 0;
  m_boOfficerGodWings := False;
  m_wCentsOfficerLevel := 0;                                                                        //仙官等级
  m_nCentsOfficerExp := 0;                                                                          //仙官经验
  FillChar(m_VerifyCodeInfo, SizeOf(TVerifyCodeInfo), #0);
  m_btComboPoint := 0;                                                                              //连击点
  m_btComboTime := 0;                                                                               //连击点增加时间
  m_btBroilHotStatuTime := 0;                                                                       //炙热效果
  m_btRandomDanceTime := 0;
  m_btGodRunTime := 0;                                                                              //神行
  m_nMeatQuality := 0;
  FillChar(m_UserConstellation, SizeOf(TUserConstellation), #0);
  FillChar(m_GemSourcePow, SizeOf(TGemSourcePow), #0);
  FillChar(m_GemLvInfo, SizeOf(TGemLvInfo), #0);
  m_boSecretMode := False;
  m_sSecretName := '';
  m_btSecretDress := 0;
  m_btSecretWeapon := 0;
  m_btWalkLotus := 0;
  m_nBodyLeathery := 0;
  m_nSlaveType := 0;
  m_boVehicleMaterial := False;
  m_boRideOrthrusMode := False;
  m_boFirstCarpenter := False;                                                                      //天下第一匠神
  m_boGameManage := False;                                                                          //显示GM封号
  m_boSoaring := False;                                                                             //显示渡劫飞升封号
  m_btKingTitle := 0;                                                                               //王爵封号
  m_btLoverTitle := 0;                                                                              //情人节封号
  m_btColorSkill := 0;                                                                              //彩色技能
  m_btLoverEvents := 0;
  m_boBianShen := False;
  m_nHiContribution := 0;
  m_nCurContribution := 0;
  FillChar(m_btSelfCreated, SizeOf(TSelfCreated), #0);                                              //自创材料
  FillChar(m_SecretInfo, SizeOf(TSecretInfo), #0);

  m_nDreamsType := 0;
  m_nKillMonExpLoitRate := 100;
  m_dwKillMonExpLoitRateTime := 0;
  m_nKillMonRepressDemonRate := 100;
  m_dwKillMonRepressDemonRateTime := 0;
  FillChar(m_DreamsPass, SizeOf(TDreamsPass), 0);
  FillChar(m_ExpeditionBox, SizeOf(TExpeditionBox), #0);
  m_MagicOrder := '';
  m_btMagicOrder := 0;
  m_boComboMagic := false;
  m_ConsignClass := 0;
  m_GuildOfficial := 0;
  m_KnockEggCount := 0;
  FillChar(m_HumanDisarm, SizeOf(TDisarmInfo), #0);
  FillChar(m_GuildSkill, SizeOf(TGuildManorSkill), #0);
  FillChar(m_ScratchCard, SizeOf(TScratchCard), #0);
  FillChar(m_VehicleExp, SizeOf(TVehicleExp), #0);
  FillChar(m_RedPacket, SizeOf(TRedPacketsInfo), #0);
  FillChar(m_ClanInsignia, SizeOf(TClanInsignia), #0);
  FillChar(m_ButchItem, SizeOf(TButchItem), #0);
  FillChar(m_RepressDemon, SizeOf(TRepressDemon), #0);
  FillChar(m_HumWingInfo, SizeOf(THumWingInfo), #0);
  FillChar(m_HumEquipsInfo, SizeOf(TRepressDemonEquipsInfo), #0);
  m_boRulerhalo := false;
  m_boUnSafeZone := False;
  m_btDemonMode := 0;
  m_btDemonForce := 0;
  m_wMasterGeneral := 0;
  FillChar(m_HumanDecLucky, SizeOf(TDisarmInfo), #0);
  FillChar(m_dwStopMagic, SizeOf(m_dwStopMagic), 0);
  FillChar(m_ErgumCount, SizeOf(TErgumCount), 0);
  m_DealCreat := nil;
  FillChar(m_boSuitSub, SizeOf(m_boSuitSub), 0);
  FillChar(m_ExemptHurt, SizeOf(m_ExemptHurt), 0);


  if btFree then
    ClearFree();
end;

procedure TPlayObject.ClearFree();
var
  i, nCheckCode                         : Integer;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::Destroy Code:=%d';
begin
  nCheckCode := 0;
  try
    nCheckCode := 1;

    m_MasterList.Clear;

    nCheckCode := 2;
    for i := 0 to m_DynamicVarList.Count - 1 do begin
      Dispose(pTDynamicVar(m_DynamicVarList.Items[i]));
    end;
    m_DynamicVarList.Clear;

    nCheckCode := 3;
    for i := 0 to m_DelayCall.Count - 1 do begin
      Dispose(pTDelayCall(m_DelayCall.Items[i]));
    end;
    m_DelayCall.Clear;

    nCheckCode := 4;
    for i := 0 to m_ArrowList.Count - 1 do begin
      Dispose(pTArrowRec(m_ArrowList.Objects[i]));
    end;
    m_ArrowList.Clear;

    for i := 0 to m_PetSoulItemsList.Count - 1 do begin
      Dispose(pTPetSoulItem(m_PetSoulItemsList.Items[i]));
    end;
    m_PetSoulItemsList.Clear;

    if m_pSwitchPneuma <> nil then
      Dispose(m_pSwitchPneuma);
    m_pSwitchPneuma := nil;

    //纹佩宝盒
    for i := 0 to m_AchievementList.Count - 1 do begin
      Dispose(PTAchievementInfo(m_AchievementList.Items[i]));
    end;
    m_AchievementList.Clear;

    //自定义变量
    for i := 0 to m_CustomTableList.Count - 1 do begin
      TSQLiteTable(m_CustomTableList.Items[i]).free;
    end;
    m_CustomTableList.Clear;

    if m_KnockEggList.Count > 0 then begin
      for I := 0 to m_KnockEggList.Count - 1 do begin
        if pTKnockEggItem(m_KnockEggList.Items[i]) <> nil then
          Dispose(pTKnockEggItem(m_KnockEggList.Items[i]));
      end;
    end;
    m_KnockEggList.Clear;

    if m_CheckCondition.Count > 0 then begin
      for I := 0 to m_CheckCondition.Count - 1 do begin
        if pTCondition(m_CheckCondition.Items[i]) <> nil then
          Dispose(pTCondition(m_CheckCondition.Items[i]));
      end;
    end;
    m_CheckCondition.Clear;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
end;

//执行消息命令

function TPlayObject.Operate(ProcessMsg: pTProcessMessage): Boolean;
var
  CharDescEx                            : TCharDescEx;
  CharDesc                              : TCharDesc;
  UserShop                              : TUserShop;
  nObjCount                             : Integer;
  nArrItem                              : array[0..2] of Integer;
  s1C, sName, sData, sTmp, sGuildName   : string;
  MessageBodyWL                         : TMessageBodyWL;
  MessageBodyW                          : TMessageBodyW;
  ShortMessage                          : TShortMessage;
  CombineSkillEffect                    : TCombineSkillEffect;
  dwDelayTime                           : LongWord;
  nMsgCount                             : Integer;
  Magic                                 : pTMagic;
  i                                     : Integer;
  AttackObject                          : TBaseObject;
  NewMagicEff                           : TNewMagicEff;
  HealthEffect                          : THealthEffect;
  MagicEffect                           : TMagicEffect;
  nX, nY, n18, n1C                      : Integer;
  StdItem                               : pTStdItem;
  btShiEld, btRShape                    : byte;
  btType                                : Byte;
  boBindGameGold                        : Boolean;
  ColorItem                             : TColorItem;
  UserItem                              : pTUserItem;
resourcestring
  sHint1                                = '神奇的力量凝聚,你的元神分身被唤醒了。';
  sHint2                                = '目前不能摆摊!!!';
  sHint3                                = '目前不支持拍卖,请选择原地摆摊';
  sHint4                                = '神奇的力量散去,你的元神分身开始沉睡。';
  sHint5                                = '地图对象为空,无法处理地图切换!';
  sSpeedExcept                          = '速度异常 Ident: %d Time: %d';
  sOpDelay                              = '操作延迟 Ident: %d Time: %d';

begin
  Result := True;
  case ProcessMsg.wIdent of
    RM_TURN,
      RM_PUSH,
      RM_RUSH,
      RM_RUSHKUNG,
      RM_PUSH_LION: begin
        if (ProcessMsg.BaseObject <> nil) and ((TBaseObject(ProcessMsg.BaseObject) <> Self) or (ProcessMsg.wIdent = RM_PUSH) or
          (ProcessMsg.wIdent = RM_RUSH) or (ProcessMsg.wIdent = RM_RUSHKUNG) or (ProcessMsg.wIdent = RM_PUSH_LION)) then begin
          case ProcessMsg.wIdent of
            RM_PUSH:
              m_defMsg := MakeDefaultMsg(SM_BACKSTEP,
                Integer(ProcessMsg.BaseObject),
                ProcessMsg.nParam1 {x},
                ProcessMsg.nParam2 {y},
                MakeWord(ProcessMsg.wParam {dir},
                TBaseObject(ProcessMsg.BaseObject).m_btGender {light}));
            RM_RUSH:
              m_defMsg := MakeDefaultMsg(SM_RUSH,
                Integer(ProcessMsg.BaseObject),
                ProcessMsg.nParam1,
                ProcessMsg.nParam2,
                ProcessMsg.wParam);
            RM_RUSHKUNG:
              m_defMsg := MakeDefaultMsg(SM_RUSHKUNG,
                Integer(ProcessMsg.BaseObject), ProcessMsg.nParam1,
                ProcessMsg.nParam2, MakeWord(ProcessMsg.wParam,
                TBaseObject(ProcessMsg.BaseObject).m_btGender));
            RM_PUSH_LION:
              m_defMsg := MakeDefaultMsg(SM_LIONCRSH,
                Integer(ProcessMsg.BaseObject), ProcessMsg.nParam1,
                ProcessMsg.nParam2, MakeWord(ProcessMsg.wParam,
                TBaseObject(ProcessMsg.BaseObject).m_btGender));
          else begin
              m_defMsg := MakeDefaultMsg(SM_TURN,
                Integer(ProcessMsg.BaseObject),
                ProcessMsg.nParam1,
                ProcessMsg.nParam2,
                MakeWord(ProcessMsg.wParam, TBaseObject(ProcessMsg.BaseObject).m_btGender));
            end;
          end;

          if ProcessMsg.wIdent = RM_PUSH_LION then begin
            CharDesc.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
            CharDesc.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
            CharDesc.Featurex := ProcessMsg.nParam3;
            s1C := EnCodeBuffer(@CharDesc, SizeOf(TCharDesc));
          end else begin
            CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
            CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
            CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
            s1C := EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx));
          end;

          if (ProcessMsg.wIdent <> RM_PUSH_LION) then begin
            if (ProcessMsg.sMsg <> '') then begin
              nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
              sTmp := ProcessMsg.sMsg + '/' + IntToStr(nObjCount) + TBaseObject(ProcessMsg.BaseObject).GetCharTurnMsg;
              s1C := s1C + EnCodeBuffer(@sTmp[1], Length(sTmp));                                    //sTmp[1]不包含字符串长度
            end else if ProcessMsg.BaseObject <> nil then begin
              if (CheckSPCode(TBaseObject(Self).m_dwRuleCtrlCode, SP_MON_DARKENMONSTER)) or (TBaseObject(ProcessMsg.BaseObject).m_btRaceServer = 23) then begin
                nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
                sTmp := TBaseObject(ProcessMsg.BaseObject).GetShowName() + '/' + IntToStr(nObjCount) + TBaseObject(ProcessMsg.BaseObject).GetCharTurnMsg;
                s1C := s1C + EnCodeBuffer(@sTmp[1], Length(sTmp));
              end;
            end;
          end;
          SendSocket(@m_defMsg, s1C);

          if (ProcessMsg.wIdent = RM_TURN) and (ProcessMsg.sMsg <> '') then begin
            if (TBaseObject(ProcessMsg.BaseObject).m_btRaceServer = RC_PLAYOBJECT) then begin

              //发送Featur的消息
              i := TBaseObject(ProcessMsg.BaseObject).GetFeatureToLong(Self);
              m_defMsg := MakeDefaultMsg(SM_FEATURECHANGED,
                Integer(ProcessMsg.BaseObject),
                LoWord(i),
                HiWord(i),
                TBaseObject(ProcessMsg.BaseObject).GetGender);
              SendSocket(@m_defMsg, TBaseObject(ProcessMsg.BaseObject).GetFeatureChangedMsg());

              //金刚护体、风影盾等
              if (TBaseObject(ProcessMsg.BaseObject).m_nMagicStatus in [0..255]) then
                SendDefMessage(SM_FENGHAO,
                  Integer(ProcessMsg.BaseObject),
                  TBaseObject(ProcessMsg.BaseObject).m_nMagicStatus,
                  TBaseObject(ProcessMsg.BaseObject).m_nCharStatus,
                  0, '');
              //幻彩、幻影套装
              if TBaseObject(ProcessMsg.BaseObject).m_wHuancaiSuite > 0 then
                SendDefMessage(SM_FENGHAO,
                  Integer(ProcessMsg.BaseObject),
                  16,
                  TBaseObject(ProcessMsg.BaseObject).m_wHuancaiSuite,
                  0, '');

              //发送封号和翅膀
              if (TBaseObject(ProcessMsg.BaseObject).m_wExtraLevel > 0) or
                (TBaseObject(ProcessMsg.BaseObject).m_btAmbitLevel > 0) then begin
                if (TBaseObject(ProcessMsg.BaseObject).m_btRaceServer = RC_PLAYOBJECT) then
                  SendDefMessage(SM_FENGHAO,
                    Integer(ProcessMsg.BaseObject),
                    MakeWord(8, LoByte(TBaseObject(ProcessMsg.BaseObject).m_wExtraLevel)),          //元神境界
                    TBaseObject(ProcessMsg.BaseObject).GetPneumaAmbit,
                    HiByte(TBaseObject(ProcessMsg.BaseObject).m_wExtraLevel),
                    TBaseObject(ProcessMsg.BaseObject).GetExtraLevelName)
                else if (TBaseObject(ProcessMsg.BaseObject).m_wExtraLevel = 2) then
                  SendDefMessage(SM_FENGHAO,
                    Integer(ProcessMsg.BaseObject),
                    MakeWord(8, _Max(0,
                    TBaseObject(ProcessMsg.BaseObject).m_wExtraLevel - 1)),
                    0,
                    0,
                    '');
              end;
              if TBaseObject(ProcessMsg.BaseObject).m_wBianshenAppr <> 0 then begin
                SendDefMessage(SM_FENGHAO,
                  Integer(ProcessMsg.BaseObject),
                  64,
                  TBaseObject(ProcessMsg.BaseObject).m_wBianshenImg,
                  TBaseObject(ProcessMsg.BaseObject).m_wBianshenAppr, '');
              end;

              //金刚护体,护身真气 绿色血条
              if (TBaseObject(ProcessMsg.BaseObject).m_wStatusTimeArr[STATE_HUSHENZHENQI] > 0) then
                SendDefMessage(SM_HIDE,
                  Integer(ProcessMsg.BaseObject),
                  CalcCent(TBaseObject(ProcessMsg.BaseObject).m_nHushenDura,
                  TBaseObject(ProcessMsg.BaseObject).m_nHushenDuraMax),
                  100,
                  g_HushenLvColor[Min(TBaseObject(ProcessMsg.BaseObject).m_btMagHuShenDefenceLevel, 7)],
                  '')
              else if (TBaseObject(ProcessMsg.BaseObject).m_wStatusTimeArr[STATE_JINGANGHUTI] > 0) then
                SendDefMessage(SM_HIDE,
                  Integer(ProcessMsg.BaseObject),
                  CalcCent(TBaseObject(ProcessMsg.BaseObject).m_nHushenDura,
                  TBaseObject(ProcessMsg.BaseObject).m_nHushenDuraMax),
                  100,
                  g_HushenLvColor[Min(TBaseObject(ProcessMsg.BaseObject).m_btMagJingangDefenceLevel, 7)],
                  '');

              //融合元神的神魂值
              if TBaseObject(ProcessMsg.BaseObject).m_boPneuma and (ProcessMsg.BaseObject is TPlayObject) then begin
                if TPlayObject(ProcessMsg.BaseObject).m_boInosculatePneuma and TPlayObject(ProcessMsg.BaseObject).m_SpiritInfo.boMag then begin
                  if (TPlayObject(ProcessMsg.BaseObject).m_PneumaObject = Self) then begin
                    m_defMsg := MakeDefaultMsg(SM_SPIRITHP,
                      Integer(ProcessMsg.BaseObject),
                      TPlayObject(ProcessMsg.BaseObject).m_SpiritInfo.wCurHP,
                      TPlayObject(ProcessMsg.BaseObject).m_SpiritInfo.wMaxHP,
                      0);
                  end else begin
                    m_defMsg := MakeDefaultMsg(SM_SPIRITHP,
                      Integer(ProcessMsg.BaseObject),
                      CalcCent(TPlayObject(ProcessMsg.BaseObject).m_SpiritInfo.wCurHP,
                      TPlayObject(ProcessMsg.BaseObject).m_SpiritInfo.wMaxHP),
                      100,
                      0);
                  end;
                  n18 := 0;
                  SendSocket(@m_defMsg, EnCodeBuffer(@n18, 2));
                end;
              end;

              //技能效果
              m_defMsg := MakeDefaultMsg(SM_CHARSTATUSCHANGED,
                Integer(ProcessMsg.BaseObject),
                LoWord(TBaseObject(ProcessMsg.BaseObject).m_nCharStatus),
                HiWord(TBaseObject(ProcessMsg.BaseObject).m_nCharStatus),
                TBaseObject(ProcessMsg.BaseObject).m_nHitSpeed);

              SendSocket(@m_defMsg, TBaseObject(ProcessMsg.BaseObject).GetCharStatusMsg);

              //发送心魔、人类 攻击值
{$IF DEMONSERVER = 1}
              if m_btDemonMode > 0 then begin
                g_PacketManage3.Init;
                g_PacketManage3.WriteByte(1);
                g_PacketManage3.WriteByte(m_btDemonForce);
                g_PacketManage3.WriteInteger(Integer(Self));
                g_PacketManage3.WriteInteger(0);
                SendRefMsg(RM_DEMONHIT, 0, Integer(Self), 0, 0, g_PacketManage3.GetMsg);
                if (m_btDemonForce = 0) then begin
                  m_btDemonMode := 0;
                end;
              end;
{$IFEND}
            end;
            //元神灵珠模式
            if TBaseObject(ProcessMsg.BaseObject).m_boPneuma and
              (TBaseObject(ProcessMsg.BaseObject).m_boPneumaEffMode) then
              SendDefMessage(3082, Integer(ProcessMsg.BaseObject), 1, 0, 0, '');

            //发送摆摊状态
            if TBaseObject(ProcessMsg.BaseObject).IsShop then begin
              TBaseObject(ProcessMsg.BaseObject).GetUserShop(@UserShop);
              //发送操作结果和商店名称
              if (TBaseObject(ProcessMsg.BaseObject).m_btRaceServer = RC_PLAYOBJECT) then
                m_defMsg := MakeDefaultMsg(SM_USERDOSHOP,
                  Integer(ProcessMsg.BaseObject),
                  TBaseObject(ProcessMsg.BaseObject).m_nCurrX,
                  TBaseObject(ProcessMsg.BaseObject).m_nCurrY,
                  TBaseObject(ProcessMsg.BaseObject).m_btDirection)
              else
                m_defMsg := MakeDefaultMsg(SM_PETDOSHOP,
                  Integer(ProcessMsg.BaseObject),
                  TBaseObject(ProcessMsg.BaseObject).m_nHomeX,
                  TBaseObject(ProcessMsg.BaseObject).m_nHomeY,
                  TBaseObject(ProcessMsg.BaseObject).m_btJob);
              SendSocket(@m_defMsg, EnCodeBuffer(@UserShop, 62));
            end;
            //弓箭手下跪
            if m_boNeedKneel then begin
              if (TBaseObject(ProcessMsg.BaseObject).m_btRaceServer in [RC_GUARD, RC_ARCHERGUARD]) then begin
                TBaseObject(ProcessMsg.BaseObject).m_btDirection := GetNextDirection(TBaseObject(ProcessMsg.BaseObject).m_nCurrX,
                  TBaseObject(ProcessMsg.BaseObject).m_nCurrY,
                  m_nCurrX,
                  m_nCurrY);
                TBaseObject(ProcessMsg.BaseObject).SendRefMsg(RM_HIT,
                  MakeWord(TBaseObject(ProcessMsg.BaseObject).m_btDirection, 1),
                  TBaseObject(ProcessMsg.BaseObject).m_nCurrX,
                  TBaseObject(ProcessMsg.BaseObject).m_nCurrY,
                  0,
                  TBaseObject(ProcessMsg.BaseObject).GetShowName);
              end;
            end;
            //灵魂墙
            if TBaseObject(ProcessMsg.BaseObject).m_boSpiritWall then begin
              SendMsg(TBaseObject(ProcessMsg.BaseObject), RM_GHOST, 0, 0, 0, 0, '');
            end;
            //投石车 1140 1137

          end;
        end;
      end;
    CM_WALK: begin                                                                                  //3011                     //行走   //---------------
        if ClientWalkXY(ProcessMsg.wIdent, ProcessMsg.nParam1 {x}, ProcessMsg.nParam2 {y}, ProcessMsg.boLateDelivery, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;
          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
          if g_Config.boStartMapEvent then begin
            StartMapEventOfWalk();                                                                  //跑步事件触发
          end;
          //生活技能挖掘中移动中断
          if (m_ButchItem.PlayObject > 0) and (m_ButchItem.BaseObject > 0) and (m_dwButchItemTime > 0) then begin
            m_dwButchItemTime := 0;
            g_PacketManage3.Init;
            g_PacketManage3.WriteInteger(m_ButchItem.PlayObject);
            g_PacketManage3.FillWrite(8, 0);
            g_PacketManage3.WriteInteger($05);
            g_PacketManage3.WriteByte(0);
            g_PacketManage3.WriteByte(m_btDirection);
            g_PacketManage3.FillWrite(6, 0);
            SendDefMessage(2161, Integer(self), 0, 0, 0, g_PacketManage3.GetMsg, True);
            m_sScriptParam[0] := TBaseObject(m_ButchItem.BaseObject).m_sCharName;
            ExecuteScript(g_FunctionNPC, '@采集中断_' + IntToStr(m_ButchItem.nID));
          end;
        end else begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetWalkMsgCount();
              if nMsgCount >= g_Config.nMaxWalkMsgCount then begin
                Inc(m_nOverSpeedCount);                                                             //超速次数
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sWalkOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                if m_boTestSpeedMode then
                  SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
              end else begin
                if (dwDelayTime > g_Config.dwDropOverSpeed) and
                  (g_Config.btSpeedControlMode = 1) and m_boFilterAction then begin
                  SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  if m_boTestSpeedMode then
                    SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                    ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '',
                    dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    RM_WALK: begin                                                                                  //10002        //走
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_WALK, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, MakeWord(ProcessMsg.wParam,
            TBaseObject(ProcessMsg.BaseObject).m_nLight));
          CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
          CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
          CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
          SendSocket(@m_defMsg, EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx)));
        end;
      end;
    CM_RUN: begin                                                                                   //3013       //跑
        if ClientRunXY(ProcessMsg.wIdent, ProcessMsg.nParam1 {x},
          ProcessMsg.nParam2 {y}, ProcessMsg.nParam3, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;
          SendSocket(nil, sSTATUS_GOOD + IntToStr(ProcessMsg.nParam1) + '/' + IntToStr(ProcessMsg.nParam2));
          if g_Config.boStartMapEvent then begin
            StartMapEventOfRun();                                                                   //跑步事件触发
          end;
          //生活技能挖掘中移动中断
          if (m_ButchItem.PlayObject > 0) and (m_ButchItem.BaseObject > 0) and (m_dwButchItemTime > 0) then begin
            m_dwButchItemTime := 0;
            g_PacketManage3.Init;
            g_PacketManage3.WriteInteger(m_ButchItem.BaseObject);
            g_PacketManage3.FillWrite(8, 0);
            g_PacketManage3.WriteInteger($05);
            g_PacketManage3.WriteByte(0);
            g_PacketManage3.WriteByte(m_btDirection);
            g_PacketManage3.FillWrite(6, 0);
            SendDefMessage(2161, Integer(self), 0, 0, 0, g_PacketManage3.GetMsg, True);
            m_sScriptParam[0] := TBaseObject(m_ButchItem.BaseObject).m_sCharName;
            ExecuteScript(g_FunctionNPC, '@采集中断_' + IntToStr(m_ButchItem.nID));
          end;
        end else begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetRunMsgCount();
              if nMsgCount >= g_Config.nMaxRunMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sRunOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
              end else begin
                if (dwDelayTime > g_Config.dwDropOverSpeed) and
                  (g_Config.btSpeedControlMode = 1) and m_boFilterAction then begin
                  SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  if m_boTestSpeedMode then
                    SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, CM_RUN, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    RM_RUN: begin                                                                                   ////跑
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_RUN, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, MakeWord(ProcessMsg.wParam,
            TBaseObject(ProcessMsg.BaseObject).m_nLight));
          CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
          CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
          CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
          s1C := EnCodeBuffer(@CharDescEx, SizeOf(CharDescEx));

          nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
          if ProcessMsg.sMsg <> '' then
            s1C := s1C + (EnCodeString(ProcessMsg.sMsg + '/' + IntToStr(nObjCount)));
          SendSocket(@m_defMsg, s1C);
        end;
      end;
    RM_HIT: begin                                                                                   ////攻击
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_HIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
          CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
          SendSocket(@m_defMsg, EnCodeBuffer(@CharDescEx, 8));
        end;
      end;
    CM_SPELL: begin                                                                                 //3017  004D76FD     //魔法攻击
        if not m_boNoAttackMode and ClientSpellXY(ProcessMsg.wIdent,
          ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2,
          TBaseObject(ProcessMsg.nParam3), ProcessMsg.boLateDelivery, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;

          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));

        end else begin
          if m_boNoAttackMode then
            SysMsg('观众模式不能参与攻击', c_Red, t_Hint);

          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));        //-----------传世行走失败
            end else begin
              nMsgCount := GetSpellMsgCount();
              if nMsgCount >= g_Config.nMaxSpellMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sSpellOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));      //-----------传世行走失败
              end else begin
                if (dwDelayTime > g_Config.dwDropOverSpeed) and
                  (g_Config.btSpeedControlMode = 1) and m_boFilterAction then begin
                  SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));    //-----------传世行走失败
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  if m_boTestSpeedMode then
                    SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                    ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    RM_SPELL: begin                                                                                 // 10007//魔法
        if (TBaseObject(ProcessMsg.BaseObject) <> Self) or GetSpellToSelf(ProcessMsg.nParam3) then begin
          m_defMsg := MakeDefaultMsg(SM_SPELL,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,                                                                     //X
            ProcessMsg.nParam2,                                                                     //Y
            ProcessMsg.wParam);                                                                     //btEffect
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;
    RM_SPELL2: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_POWERHIT,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_HEALTHSPELLCHANGED: begin                                                                    //10052
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_HEALTHSPELLCHANGED,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam3,
            ProcessMsg.nParam2);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;
    CM_HIT,                                                                                         //3014                 //攻击动作
      CM_HEAVYHIT,                                                                                  //3015
      CM_BIGHIT,                                                                                    //3016
      CM_POWERHIT,                                                                                  //3018
      CM_LONGHIT,                                                                                   //3019
      CM_WIDEHIT,                                                                                   //3024
      CM_CRSHIT,
      CM_TWNHIT,
      CM_FIREHIT,
      CM_3026: begin                                                                                //3025
        //        {$IF USESDK = DEBUG}
        //        MainOutMessage(Format('攻击动作:%s-%d-%d-%d-%d-%d %s',
        //          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
        //          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
        //        {$IFEND}

        if not m_boNoAttackMode and ClientHitXY(ProcessMsg.wIdent {ident},
          ProcessMsg.nParam1 {x}, ProcessMsg.nParam2 {y}, ProcessMsg.wParam {dir},
          ProcessMsg.nParam3, ProcessMsg.boLateDelivery, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;

          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end else begin
          if m_boNoAttackMode then
            SysMsg('观众模式不能参与攻击', c_Red, t_Hint);

          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetHitMsgCount();
              if nMsgCount >= g_Config.nMaxHitMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sHitOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
              end else begin
                if (dwDelayTime > g_Config.dwDropOverSpeed) and
                  (g_Config.btSpeedControlMode = 1) and m_boFilterAction then begin
                  //SendUpdateMsg(Self, 65535, 0, m_nCurrX, m_nCurrY, 0, '');
                  SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  if m_boTestSpeedMode then begin
                    SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  end;
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    RM_ANYINGLEIDIAN: begin                                                                         //显示暗影雷电的效果
        ShortMessage.Ident := $12;
        ShortMessage.wMsg := ProcessMsg.nParam3;
        m_defMsg := MakeDefaultMsg($2BDC,
          ProcessMsg.nParam1,
          LoWord(ProcessMsg.nParam2),
          HiWord(ProcessMsg.nParam2),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, EnCodeBuffer(@ShortMessage,
          SizeOf(TShortMessage)));
      end;
    CM_3078: begin                                                                                  //释放了元神
        DeCodeBuffer(ProcessMsg.sMsg, @nObjCount, SizeOf(Integer));
        if (m_PneumaObject <> nil) and (nObjCount = Integer(m_PneumaObject)) then begin
          SysMsg(sHint1, c_Red, t_Hint);
        end;
{$IF USESDK = DEBUG}
        MainOutMessage(Format('元神消息:%s-%d-%d-%d-%d-%d %s-%d',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg, nObjCount]));
{$IFEND}
      end;
    RM_SENDMYNAME: begin
        SendDefMessage(SM_9609, Integer(Self), 0, 0, 0, m_sCharName);
      end;
    CM_3080: begin                                                                                  //释放或收起元神
        PneumaLogin();
{$IF USESDK = DEBUG}
        MainOutMessage(Format('元神消息:%s-%d-%d-%d-%d-%d %s-%s',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)]));
{$IFEND}
      end;
    CM_OPPNEUMAITEM: begin                                                                          //把人物包裹物品移动到元神包裹
        ClientOpPneumaBagItem(ProcessMsg.sMsg);
      end;
    CM_3077: begin                                                                                  //人物和元神之间交换金币
        ClientOpPneumaGold(ProcessMsg.sMsg)
      end;
    CM_3079: begin                                                                                  //估计是寻找主人的位置消息
        if m_boPneuma and (m_PneumaObject <> nil) and ((m_PEnvir <> m_PneumaObject.m_PEnvir) or
          (abs(m_nCurrX - m_PneumaObject.m_nCurrX) > 15) or (abs(m_nCurrY - m_PneumaObject.m_nCurrY) > 15)) then begin
          if m_PneumaObject.GetRightPosition(nX, nY) then begin
            if m_PneumaObject.GetCanMovePosition(nX, nY, 3, n18, n1C) then begin
              SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
              SpaceMove(m_PneumaObject.m_sMapName, n18, n1C, 0, nil);
            end;
          end;
        end;
      end;
    CM_3082: begin                                                                                  //在灵珠模式和人形模式间切换
{$IF USESDK = DEBUG}
        MainOutMessage(Format('元神灵珠消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        ChangePneumaState();
      end;
    RM_YSSTATECHANGED: begin
        SendDefMessage(3082, ProcessMsg.nParam1, ProcessMsg.wParam, 0, 0, '');
      end;
    CM_OPENRANK: begin
        if (ProcessMsg.nParam2 = 0) then begin                                                      //0、自己点的; 1、服务器更新  //查看英雄榜
          if not g_Config.boUseRankList then
            ExecuteScript(g_ManageNPC, '@OpenRank')
          else begin
            if m_WAbil.level >= g_Config.nViewRankLevel then begin
{$IF DEMONSERVER = 1}
              if g_Config.boNightMareServer then
                SendDefMessage($9702, Integer(Self), g_Config.nUseRanking, 2, 0, '')
              else
{$IFEND}
                SendDefMessage($9702, Integer(Self), g_Config.nUseRanking, 1, 0, '')
            end else begin
              SysMsg(Format('您当前等级还没有达到%d级,无法查询排行榜', [g_Config.nViewRankLevel]), c_Red, t_Hint);
            end;
          end;
        end;
      end;
    CM_SENDRANK: begin                                                                              //查询对应的排行榜
        if m_WAbil.level >= g_Config.nRankLevel then
          g_RankManage.OnQueryRankListOrd(Self, ProcessMsg.nParam2, ProcessMsg.wParam);
      end;
    CM_RECALLEVIL: begin
        ClientEvilOp(ProcessMsg.nParam2, ProcessMsg.nParam1,
          MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam));
{$IF USESDK = DEBUG}
        MainOutMessage(Format('心魔控制消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    CM_ERNIE: begin
        ClientErnie(ProcessMsg.nParam2);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('神龙献宝消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    CM_HUANJING: begin
        ClientOpenHuanjing(ProcessMsg.nParam1, ProcessMsg.nParam2,
          ProcessMsg.nParam3);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('天关幻境消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    CM_PERSONSET: begin                                                                             //个性化设置
{$IF USESDK = DEBUG}
        MainOutMessage(Format('内挂设置消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        ClientPersonalSet(ProcessMsg.wParam, ProcessMsg.nParam2,
          ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    CM_WOLSHOP: begin
        if ProcessMsg.nParam2 = 1 then begin
          //滚动消息
          m_defMsg := MakeDefaultMsg(SM_WOLSHOP, Integer(Self), 0, 0, 0);
          SendSocket(@m_defMsg, EnCodeString(UserEngine.GetShopScrollMsg));
          //热点标题
          m_defMsg.Param := 10;
          SendSocket(@m_defMsg, EnCodeString(UserEngine.GetShopHotTitle));
          //热销排行榜
          m_defMsg.Param := 1;
          SendSocket(@m_defMsg, EnCodeString(UserEngine.GetHotSellItems));
          //首页子栏目列表
          m_defMsg.Param := 2;
          s1C := UserEngine.GetBandItems('10');
          SendSocket(@m_defMsg, EnCodeString(s1C));
          //首页第一子栏目商品
          m_defMsg.Param := 3;
          s1C := UserEngine.GetSubBandItems(self, '1010');
          SendSocket(@m_defMsg, EnCodeString(s1C));
        end else if ProcessMsg.nParam2 = 2 then begin
          //子栏目列表
          m_defMsg := MakeDefaultMsg(SM_WOLSHOP, Integer(Self), 2, 0, 0);
          s1C := UserEngine.GetBandItems(DeCodeString(ProcessMsg.sMsg));
          SendSocket(@m_defMsg, EnCodeString(s1C));
          //第一子栏目商品列表
          if s1C <> '&' then begin
            m_defMsg := MakeDefaultMsg(SM_WOLSHOP, Integer(Self), 3, 0, 0);
            s1C := UserEngine.GetSubBandItems(Self, DeCodeString(ProcessMsg.sMsg) + '10');
            SendSocket(@m_defMsg, EnCodeString(s1C));
          end;
        end else if ProcessMsg.nParam2 = 3 then begin                                               //查询子栏目商品列表
          s1C := DeCodeString(ProcessMsg.sMsg);
          if s1C <> '&' then begin
            m_defMsg := MakeDefaultMsg(SM_WOLSHOP, Integer(Self), 3, 0, 0);
            s1C := UserEngine.GetSubBandItems(Self, s1C);
            SendSocket(@m_defMsg, EnCodeString(s1C));
          end;
        end else if ProcessMsg.nParam2 = 4 then begin
          //商品描述信息
          s1C := UserEngine.GetStdItemDesc(Self, DeCodeString(ProcessMsg.sMsg));
          m_defMsg := MakeDefaultMsg(SM_WOLSHOP, Integer(Self), 4, 0, 0);
          SendSocket(@m_defMsg, EnCodeString(s1C));
        end else if (ProcessMsg.nParam2 in [5, 7, 16]) or (ProcessMsg.nParam2 = $0105) then begin   //购买 5=元宝  16=绑定元宝
          SetLength(s1C, Round(Length(ProcessMsg.sMsg) * 3 / 4));
          boBindGameGold := ProcessMsg.nParam2 = 16;
          DeCodeBuffer(ProcessMsg.sMsg, @s1C[1], Length(s1C));
          if s1C <> '' then begin
            //商品编号 赠送人 留言
            i := 1;
            sData := GetToken(s1C, #0, i);
            sData := GetToken(s1C, #0, i);
            sTmp := GetToken(s1C, #0, i);
            if Pos(#0, s1C) > 0 then Delete(s1C, Pos(#0, s1C), Length(s1C));
            if ProcessMsg.nParam2 = $0105 then                                                      //传世商城
              UserEngine.BuyWolShopItem(Self, sData, s1C, sTmp, boBindGameGold, False)
            else                                                                                    //普通商品
              UserEngine.BuyWolShopItem(Self, sData, s1C, sTmp, boBindGameGold, True);
{$IF USESDK = DEBUG}
            MainOutMessage(Format('商城购买信息:%s-%s-%s', [sData, s1C, sTmp]));
{$IFEND}
          end;
        end else if (ProcessMsg.nParam2 = 6) then begin
          ExecuteScript(g_ManageNPC, '@OpenWolShop' + IntToStr(ProcessMsg.wParam))
        end
        else begin
{$IF CHECKNEWMSG = 1}
          MainOutMessage(Format('未知商城消息:%d-%d-%d-%d-%d %s',
            [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
            ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        end;
      end;
    CM_BAGORDER: begin                                                                              //人物下线之前保存的数据
        ClientSetBagOrder(ProcessMsg.wParam, ProcessMsg.sMsg);
      end;
    CM_OPENPETBAG: begin
        if not m_boBagSend then
          SendDelayMsg(Self, CM_QUERYBAGITEMS, 0, 0, 0, 0, '', 1000);
        m_defMsg := MakeDefaultMsg(SM_9600, DateTimeToWolTIme(Date + Time), 0, 0, 0);
        SendSocket(@m_defMsg, '');
      end;
    CM_MOVEITEMTOPETBAG: begin
        ClientStorageItemToPetBag(ProcessMsg.nParam1);
      end;
    CM_MOVEITMETOBAG: begin
        ClientTakebackPetItem(ProcessMsg.nParam1);
      end;
    CM_DOSHOP: begin                                                                                //摆摊
        ClientDoShop(ProcessMsg.nParam2, ProcessMsg.sMsg);
      end;

    CM_REQUESTDOSHOP: begin
{$IF USESDK = DEBUG}
        MainOutMessage(Format('摆摊消息 %d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        if m_boRideOn or m_PEnvir.m_MapFlag.boNoDoShop or m_boArrow then
          SysMsg(sHint2, c_Red, t_Hint)
        else begin
          case ProcessMsg.nParam2 of
            0: begin
                ClientPetStopDoShop();                                                              //停止摆摊
              end;
            2: begin                                                                                //取卖物所得
                ClientGetbackPetMoney();
              end;
            3: begin                                                                                //取摆摊物品
                if (m_Pet <> nil) then ClientGetbackPetShopItem();
              end;
            5: begin
                ClientRequestPetDoShop();                                                           //请求摆摊
              end;
            7: begin
                if (m_PackPet <> nil) then
                  SendDefMessage(34979,
                    0,
                    1,
                    0,
                    0,
                    Format('你的宠物豹在%s(%d:%d)为你守摊。', [m_PackPet.m_PEnvir.m_sMapDesc, m_PackPet.m_nCurrX, m_PackPet.m_nCurrY]))
                else
                  SendDefMessage(34979, 0, 0, 0, 0, '没有守摊的豹子');
              end;
          end;
        end;
      end;
    CM_UPDATESHOPITEM: begin                                                                        //更新宠物摊位
        ClientUpdatePetShop(ProcessMsg.nParam1, ProcessMsg.nParam3,
          ProcessMsg.sMsg);
      end;
    CM_PETDOSHOP: begin                                                                             //24245 豹子摆摊
        ClientPetDoShop(ProcessMsg.nParam1, ProcessMsg.nParam2,
          ProcessMsg.sMsg);
      end;
    RM_DOSHOP: begin
        if (ProcessMsg.BaseObject <> Self) then begin
          m_defMsg := MakeDefaultMsg(SM_USERDOSHOP,
            Integer(ProcessMsg.BaseObject),
            LoWord(ProcessMsg.nParam1),
            HiWord(ProcessMsg.nParam1),
            ProcessMsg.wParam);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;

    RM_PETDOSHOP: begin
        if (ProcessMsg.BaseObject <> Self) then begin
          m_defMsg := MakeDefaultMsg(SM_PETDOSHOP,
            ProcessMsg.nParam3,
            LoWord(ProcessMsg.nParam1),
            HiWord(ProcessMsg.nParam1),
            ProcessMsg.wParam);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;
    RM_SENDSHOPITEMS: begin
        if m_PackPet <> nil then
          m_PackPet.SendShopItems(Self, 1);
      end;
    CM_ADDFRIEND: begin
        ClientAddFriend(ProcessMsg.sMsg);
      end;
    CM_DELFRIEND: begin
        ClientDelFriend(ProcessMsg.sMsg);
      end;
    CM_RESPADDFRIEND: begin
        ClientRespAddFriend(ProcessMsg.nParam1, ProcessMsg.sMsg);
      end;
    $E67B: begin                                                                                    //点彩虹客服MM,触发脚本
        ExecuteScript(g_ManageNPC, '@客服功能');
      end;
    $9707: begin
        SendDefMessage(SM_9708, 0, 256, 0, 0, '');
        //SendDefMessage($FFFF, 0, m_nCurrX, m_nCurrY, 0, '');                                        //未知
      end;
    $0710: begin
        ExecuteScript(g_ManageNPC, '@商城功能_' + IntToStr(ProcessMsg.wParam));
      end;
    3044: ;                                                                                         //未知消息
    1811: begin
        SendDefMessage(SM_MENU_OK, Integer(Self), 0, 0, 0, sHint3);
      end;
    192: begin                                                                                      //黄榜大旗放到旗座上
        MakeFlagOwner(ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2,
          ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    193: begin                                                                                      //Ident 193 Param 1 P1 268831256 P2 1 P3 0 Msg
        ClickQueryMsg(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    654: begin                                                                                      //黄榜大旗留言
        AddFlagComment(ProcessMsg.nParam2, ProcessMsg.nParam1,
          ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    CM_TREASURE: begin
{$IF USESDK = DEBUG}
        MainOutMessage('祈愿树(宝箱):' + Format('%d-%d-%d-%d-%d-%d %s',
          [Integer(ProcessMsg.BaseObject), ProcessMsg.wIdent, ProcessMsg.wParam,
          ProcessMsg.nParam1,
            ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        GetTreasureBoxItem(ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    RM_TREASURE: begin
        m_defMsg := MakeDefaultMsg(SM_627, Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam, ProcessMsg.nParam1, 0);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_SENDFRIENDLIST: begin
        //好友的处理:装载并发送好友列表
        SendFiendList;
        //发送在线状态
        SendMeOnlineState(1);
      end;
    CM_QUERYUSERNAME: begin                                                                         //80  查询玩家名称
        ClientQueryUserName(TBaseObject(ProcessMsg.nParam1), ProcessMsg.nParam2, ProcessMsg.nParam3); //004D7931
      end;
    CM_QUERYBAGITEMS: begin                                                                         //81 查询包裹物品
        ClientQueryBagItems();
        ClientQueryTreasureBoxItems(True);                                                          //灵犀宝盒
      end;
    CM_QUERYUSERSTATE: begin                                                                        //82  查询角色状态
        ClientQueryUserState(TPlayObject(ProcessMsg.nParam1), ProcessMsg.nParam2, ProcessMsg.nParam3);
      end;
    CM_QUERYUSERSET: begin                                                                          //物品快捷交易
        ClientQueryUserSet(ProcessMsg);
      end;
    CM_64: begin                                                                                    //上马下马的命令
{$IF USESDK = DEBUG}
        MainOutMessage('骑宠信息:' + Format('%d-%d-%d-%d-%d-%d %s',
          [Integer(ProcessMsg.BaseObject), ProcessMsg.wIdent, ProcessMsg.wParam,
          ProcessMsg.nParam1,
            ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        //1秒内禁止重复上下马
        if (GetTickCount - m_dwLastRide < 500) or (not ClientRide) then
          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
      end;
    CM_DROPITEM: begin                                                                              //1000  丢掉物品
        if ClientDropItem(ProcessMsg.sMsg, ProcessMsg.nParam1) then
          SendDefMessage(SM_DROPITEM_SUCCESS, ProcessMsg.nParam1, 0, 0, 0,
            ProcessMsg.sMsg)
        else
          SendDefMessage(SM_DROPITEM_FAIL, ProcessMsg.nParam1, 0, 0, 0,
            ProcessMsg.sMsg);
      end;
    CM_PICKUP: begin                                                                                //1001  004D78F9   捡物品
        if (m_nCurrX = ProcessMsg.nParam2) and (m_nCurrY = ProcessMsg.nParam3) then
          ClientPickUpItem(ProcessMsg.nParam2, ProcessMsg.nParam3, 0);
      end;
    CM_PETPICKUP: begin                                                                             //1001  004D78F9   宠物豹捡物品
        if (m_Pet <> nil) and (not m_Pet.m_boGhost) and (not m_Pet.m_boDeath)
          and (not m_Pet.m_boDealOK) and (not m_Pet.IsShop) then
          PetPickUpItem(ProcessMsg.nParam2, ProcessMsg.nParam3);
      end;
    CM_OPENDOOR: begin                                                                              //1002    开门
        ClientOpenDoor(ProcessMsg.nParam2, ProcessMsg.nParam3);
      end;
    CM_TAKEONITEM: begin                                                                            //1003  戴上装备
        ClientTakeOnItems(ProcessMsg.nParam2, ProcessMsg.nParam1, ProcessMsg.sMsg, False);
      end;
    CM_TAKEOFFITEM: begin                                                                           //1004 取下装备
        ClientTakeOffItems(ProcessMsg.nParam2, ProcessMsg.nParam1, ProcessMsg.sMsg);
      end;
    CM_TAKEENTOPTICITEM: begin                                                                      //装备元神内视装备,魂骨
        case LoByte(ProcessMsg.nParam2) of
          0: ClientTakeOnEntopticItems(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          1: ClientTakeOffEntopticItems(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          2: ClientEntopticSmelt(HiByte(ProcessMsg.nParam2), ProcessMsg.sMsg);
        end;
      end;
    CM_ILLUMEHEARTFATEPOINT: begin
        ClientIllumeHeartPoint(LoByte(ProcessMsg.nParam3) - 1, HiByte(ProcessMsg.nParam3));
      end;

    CM_EAT: begin                                                                                   //1006       吃药、学技能
        ClientUseItems(ProcessMsg.nParam1, ProcessMsg.sMsg, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    CM_BUTCH: begin                                                                                 //1007     挖肉
        if not ClientGetButchItem(TBaseObject(ProcessMsg.nParam1),
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.wParam, dwDelayTime) then begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime <> 0 then begin
              nMsgCount := GetDigUpMsgCount();
              if nMsgCount >= g_Config.nMaxDigUpMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sBunOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));      //-----------传世行走失败
              end else begin
                if dwDelayTime < g_Config.dwDropOverSpeed then begin
                  if m_boTestSpeedMode then
                    SysMsg(Format('速度异常 Ident: %d Time: %d', [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                end else begin
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                    ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end;                                                                                      // else
          //  SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    CM_MAGICKEYCHANGE: begin                                                                        //1008  设置魔法快捷键
        ClientChangeMagicKey(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    CM_SOFTCLOSE: begin                                                                             //小退
        //if not m_boOfflineGetGamePoint then begin
        m_boReconnection := True;
        m_boSoftClose := True;
        //end;
      end;
    CM_106: begin                                                                                   //大退
        if (g_Config.boEnableOffLinePlayer or m_boSafeZoneOnLine) and not m_boDeath and not m_boGhost and InSafeZone then begin
          m_boOfflineGetGamePoint := True;
          m_sAutoSayMsg := g_sOffLineMsg;
          m_boSuperMan := g_Config.boOffLineSuperMode;
          m_boAllowDeal := False;                                                                   //禁止交易
          m_boAllowGuild := False;                                                                  //禁止加入行会
          m_boAllowGroup := False;                                                                  //禁止组队
          m_boCanMasterRecall := False;                                                             //禁止师徒传送
          m_boCanDearRecall := False;                                                               //禁止夫妻传送
          m_boAllowGuildReCall := False;                                                            //禁止行会合一
          m_boAllowGroupReCall := False;                                                            //禁止天地合一
          m_wStatusTimeArr[STATE_BUBBLEDEFENCEUP] := 0;
          m_wStatusTimeArr[STATE_JINGANGHUTI] := 0;
          m_wStatusTimeArr[STATE_HUSHENZHENQI] := 0;
          m_wStatusTimeArr[STATE_FENGYINGDUN] := 0;
          m_wStatusTimeArr[STATE_FIERYDRAGON] := 0;
          m_boAbilMag70Defence := False;
          m_boAbilMagHuShenDefence := False;
          m_boAbilMagJingangDefence := False;
          m_boAbilMagBubbleDefence := False;
          //清除宝宝
          for i := 0 to m_SlaveList.Count - 1 do begin
            TBaseObject(m_SlaveList.Items[i]).MakeGhost();
          end;
          m_SlaveList.Clear;
        end;
        //if m_boOfflineGetGamePoint then m_boSoftClose := False;
      end;
    CM_CLICKNPC: begin                                                                              //1010        点NPC
        ClientClickNPC(ProcessMsg.nParam1);
      end;
    CM_MERCHANTDLGSELECT:                                                                           //1011      商品列表选择
      ClientMerchantDlgSelect(ProcessMsg.nParam1, Trim(ProcessMsg.sMsg), ProcessMsg.nParam2);
    CM_MERCHANTQUERYSELLPRICE:                                                                      //1012 询价
      ClientMerchantQuerySellPrice(ProcessMsg.nParam1,
        MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.sMsg);
    CM_USERSELLITEM:                                                                                //1013        卖东西
      ClientUserSellItem(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.sMsg);
    CM_USERBUYITEM:                                                                                 //1014  004D7AD4   买东西
      ClientUserBuyItem(ProcessMsg.wIdent, ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.wParam, ProcessMsg.sMsg);
    CM_USERGETDETAILITEM:                                                                           //1015 004D7AB6       //取商品列表
      ClientUserBuyItem(ProcessMsg.wIdent, ProcessMsg.nParam1, 0, ProcessMsg.wParam, ProcessMsg.sMsg);
    CM_DROPGOLD: begin                                                                              //1016  004D7AFC       丢掉金币
        if ProcessMsg.nParam1 > 0 then ClientDropGold(ProcessMsg.nParam1);
      end;
    CM_1017: SendDefMessage(1, 0, 0, 0, 0, '');

    CM_GROUPMODE: begin                                                                             //1019        //改变组队模式
        if ProcessMsg.nParam2 = 0 then ClientGropuClose()
        else m_boAllowGroup := True;
        if m_boAllowGroup then
          SendDefMessage(SM_GROUPMODECHANGED, 0, 1, 0, 0, '')
        else SendDefMessage(SM_GROUPMODECHANGED, 0, 0, 0, 0, '');
      end;
    CM_CREATEGROUP: begin                                                                           //1020      //创建组队
        ClientCreateGroup(Trim(ProcessMsg.sMsg));
      end;
    CM_ADDGROUPMEMBER: begin                                                                        //1021   //增加队伍成员
        ClientAddGroupMember(Trim(ProcessMsg.sMsg));
      end;
    CM_DELGROUPMEMBER: begin                                                                        //1022   //删除队伍成员
        ClientDelGroupMember(Trim(ProcessMsg.sMsg));
      end;
    CM_USERREPAIRITEM: begin                                                                        //1023   //修理物品
        ClientRepairItem(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2,
          ProcessMsg.nParam3), ProcessMsg.wParam, ProcessMsg.sMsg);
      end;
    CM_MERCHANTQUERYREPAIRCOST: begin                                                               //1024   //询问修理价格
        ClientQueryRepairCost(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2,
          ProcessMsg.nParam3), ProcessMsg.wParam, ProcessMsg.sMsg);
      end;
    CM_DEALTRY: begin                                                                               //1025
        ClientDealTry(Trim(ProcessMsg.sMsg));                                                       //交易尝试
      end;
    CM_DEALADDITEM: begin                                                                           //1026                  添加交易物品
        ClientAddDealItem(ProcessMsg.nParam1, ProcessMsg.sMsg);
      end;
    CM_DEALDELITEM: begin                                                                           //1027                 //删除交易物品
        ClientDelDealItem(ProcessMsg.nParam1, ProcessMsg.sMsg);
      end;
    CM_DEALCANCEL: begin                                                                            //1028                  //取消交易
        ClientCancelDeal();
      end;
    CM_DEALCHGGOLD: begin                                                                           //1029                 //改变交易价格
        if ProcessMsg.nParam2 = 0 then
          ClientChangeDealGold(ProcessMsg.nParam1, 0)
        else if ProcessMsg.nParam2 = 1 then
          ClientChangeDealGold(0, ProcessMsg.nParam1);
      end;
    CM_DEALEND: begin                                                                               //1030                     //交易完成
        ClientDealEnd();
      end;
    CM_USERSTORAGEITEM: begin                                                                       //保存物品到仓库取回物品
        ClientStorageItem(TObject(ProcessMsg.nParam1),
          MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.wParam = 1,
          ProcessMsg.sMsg);
      end;
    CM_USERTAKEBACKSTORAGEITEM: begin                                                               //1032     //从仓库取回物品
        ClientTakeBackStorageItem(TObject(ProcessMsg.nParam1),
          MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.wParam = 1,
          ProcessMsg.sMsg);
      end;
    CM_WANTMINIMAP: begin                                                                           //1033                 //需要小地图
        ClientGetMinMap();
      end;
    CM_USERMAKEDRUGITEM: begin                                                                      //1034            //炼药
        ClientMakeDrugItem(TObject(ProcessMsg.nParam1), ProcessMsg.sMsg);
      end;
    CM_OPENGUILDDLG: begin                                                                          //1035                //打开行会窗口
        ClientOpenGuildDlg();
      end;
    CM_GUILDHOME: begin                                                                             //1036                   //行会首页
        ClientGuildHome();
      end;
    CM_GUILDMEMBERLIST: begin                                                                       //行会成员列表
        ClientGuildMemberList();
      end;
    CM_GUILDADDMEMBER: begin                                                                        //添加行会成员
        ClientGuildAddMember(ProcessMsg.sMsg);
      end;
    CM_GUILDDELMEMBER: begin                                                                        //删除行会成员
        ClientGuildDelMember(ProcessMsg.sMsg);
      end;
    CM_GUILDUPDATENOTICE: begin                                                                     //行会公告修改
        ClientGuildUpdateNotice(ProcessMsg.sMsg);
      end;
    CM_GUILDUPDATERANKINFO: begin                                                                   //1041         //行会职位修改
        ClientGuildUpdateRankInfo(ProcessMsg.sMsg);
      end;
    CM_GUILDEXP: begin
        if m_MyGuild <> nil then begin
          SendDefMessage(717, 0, TGuild(m_MyGuild).Count, 0, 0, TGuild(m_MyGuild).GuildsMsg(m_GuildExp));
        end;
      end;
//    CM_ADJUST_BONUS: begin                                                                          //调整技能点数
//        ClientAdjustBonus(ProcessMsg.nParam1, ProcessMsg.sMsg);
//      end;
    CM_DECOMPOSE: begin
        ClientDECOMPOSE(ProcessMsg.nParam2, ProcessMsg.nParam1);
      end;
    CM_GEMREMOVE: begin                                                                             //拆除原石
        ClientGEMREMOVE(ProcessMsg.nParam2, ProcessMsg.nParam1);
        //1044-0-39440184-2-0
{$IF USESDK = DEBUG}
        MainOutMessage(Format('%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam,
          ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    //    CM_GUILDALLY: begin                                                                             //1044                  //行会联盟
    //        ClientGuildAlly();
    //      end;
    CM_YIWANGDAN: begin                                                                             //1045     //遗忘丹
        ClientYIWANGDAN(ProcessMsg.nParam1, DeCodeString(ProcessMsg.sMsg));
      end;
    CM_TURN: begin                                                                                  //3010    004D73DD            //人物转身(出现)
        if ClientChangeDir(ProcessMsg.wIdent, ProcessMsg.nParam1 {x},
          ProcessMsg.nParam2 {y}, ProcessMsg.wParam {dir}, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;

          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end else begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetTurnMsgCount();
              if nMsgCount >= g_Config.nMaxTurnMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then begin
                    MainOutMessage(Format(g_sBunOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                  end;
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
              end else begin
                if dwDelayTime < g_Config.dwDropOverSpeed then begin
                  SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                    ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    CM_STOP: begin                                                                                  //3020 在走 动作结束时接收到
        //SendUpdateMsg(Self, 65535, 0, m_nCurrX, m_nCurrY, 0, '');
        SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrX));
        SendRefMsg(SM_204, 0, 0, 0, 0, '');
      end;
    SM_204: begin
        if ProcessMsg.BaseObject <> Self then
          SendDefMessage(SM_204, Integer(ProcessMsg.BaseObject), 0, 0, 0, '');
      end;
    CM_3021: begin                                                                                  //作揖动作
        SendRefMsg(RM_3021, m_btDirection, m_nCurrX, m_nCurrY, 0, '');
      end;
    RM_3021: begin
        if ProcessMsg.BaseObject <> Self then
          SendDefMessage(SM_3021, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam, '');
      end;
    (*
    CM_HORSERUN: begin                                                                              //3009         //骑马走
        if ClientHorseRunXY(ProcessMsg.wIdent, ProcessMsg.nParam1 {x},
          ProcessMsg.nParam2 {y}, ProcessMsg.boLateDelivery, dwDelayTime) then begin
          m_dwActionTick := GetTickCount;
          SendSocket(nil, sSTATUS_GOOD + IntToStr(ProcessMsg.nParam1) + '/' + IntToStr(ProcessMsg.nParam2));
        end else begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetRunMsgCount();
              if nMsgCount >= g_Config.nMaxRunMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then
                    MainOutMessage(Format(g_sRunOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                if m_boTestSpeedMode then
                  SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
              end else begin
                if m_boTestSpeedMode then
                  SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                  ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                Result := False;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    *)
    CM_SITDOWN: begin                                                                               //3012
        if ClientSitDownHit(ProcessMsg.nParam1, ProcessMsg.nParam2,
          ProcessMsg.wParam, dwDelayTime) then begin
          m_dwActionTick := GetTickCount();

          SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end else begin
          if (not g_Config.boDisableM2SpeedCtrl) then begin
            if dwDelayTime = 0 then begin
              SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
            end else begin
              nMsgCount := GetSiteDownMsgCount();
              if nMsgCount >= g_Config.nMaxSitDonwMsgCount then begin
                Inc(m_nOverSpeedCount);
                if m_nOverSpeedCount > g_Config.nOverSpeedKickCount then begin
                  if g_Config.boKickOverSpeed then begin
                    SysMsg(g_sKickClientUserMsg {'请勿使用非法软件!!!'}, c_Red, t_Hint);
                    m_boEmergencyClose := True;
                  end;
                  if g_Config.boViewHackMessage then
                    MainOutMessage(Format(g_sBunOverSpeed, [m_sCharName, dwDelayTime, nMsgCount]));
                end;
                //如果超速则发送攻击失败信息
                SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
              end else begin
                if dwDelayTime < g_Config.dwDropOverSpeed then begin
                  SendSocket(nil, sSTATUS_GOOD + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
                  if m_boTestSpeedMode then
                    SysMsg(Format(sSpeedExcept, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                end else begin
                  if m_boTestSpeedMode then
                    SysMsg(Format(sOpDelay, [ProcessMsg.wIdent, dwDelayTime]), c_Red, t_Hint);
                  SendDelayMsg(Self, ProcessMsg.wIdent, ProcessMsg.wParam,
                    ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, '', dwDelayTime);
                  Result := False;
                end;
              end;
            end;
          end else
            SendSocket(nil, sSTATUS_FAIL + IntToStr(m_nCurrX) + '/' + IntToStr(m_nCurrY));
        end;
      end;
    RM_170: begin                                                                                   //化身蝙蝠
        m_defMsg := MakeDefaultMsg(SM_170, Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    CM_SAY: begin                                                                                   //3030           //说
        if ProcessMsg.sMsg <> '' then begin
          ProcessUserLineMsg(ProcessMsg.sMsg, ProcessMsg.wParam);
        end;
      end;
    CM_PASSWORD: begin                                                                              //仓库密码
        ProcessClientPassword(ProcessMsg);
      end;
    RM_HORSERUN: begin                                                                              //10003 004D860A   //骑马跑
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_HORSERUN,
            Integer(ProcessMsg.BaseObject), ProcessMsg.nParam1,
            ProcessMsg.nParam2, MakeWord(ProcessMsg.wParam,
            TBaseObject(ProcessMsg.BaseObject).m_nLight));
          CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
          CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
          CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
          s1C := EnCodeBuffer(@CharDescEx, SizeOf(CharDescEx));
          nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
          if ProcessMsg.sMsg <> '' then
            s1C := s1C + (EnCodeString(ProcessMsg.sMsg + '/' +
              IntToStr(nObjCount)));
          SendSocket(@m_defMsg, s1C);
        end;
      end;
    RM_HEAVYHIT: begin                                                                              //004D88CD        //烈火
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_HEAVYHIT,
            Integer(ProcessMsg.BaseObject), ProcessMsg.nParam1,
            ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;
    RM_BIGHIT: begin                                                                                //004D893A         //半月
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_BIGHIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_POWERHIT: begin
        //        //if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
        m_defMsg := MakeDefaultMsg(SM_POWERHIT,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
        //        //end;
      end;
    $1213: begin                                                                                    //打开输入对话框
        m_defMsg := MakeDefaultMsg($1213, Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam, 0, 0);
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    $6891: begin                                                                                    //客户端输入数据保存和执行下一步代码
        ClientInput(ProcessMsg.nParam1, DeCodeString(ProcessMsg.sMsg));
      end;
    197: begin                                                                                      //刻回城石 197 Param 0 P1 1073750219 P2 512 P3 0 Msg
        RecordHomeXY(ProcessMsg.nParam1, HiByte(ProcessMsg.nParam2));
      end;
    1289: begin
        RecordHomeXY(ProcessMsg.nParam1, ProcessMsg.sMsg);                                          //完美回城仙石
      end;
    1300: begin
        ClientPerfectStoreMoveHome(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    $8810: begin                                                                                    //刻回城石、存放宝石 确认等
        ClientNamedStore(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    $8850: begin                                                                                    //弹出刻回城石的对话框
        m_defMsg := MakeDefaultMsg($8850, 0, 0, 0, 0);
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    $00C6: begin                                                                                    // 198 弹出拆分圣灵精华的对话框
{$IF USESDK = DEBUG}
        MainOutMessage(Format('%d-%d-%d-%d-%d-%d %s',
          [Integer(ProcessMsg.BaseObject),
          ProcessMsg.wIdent,
            ProcessMsg.wParam,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.sMsg]));
{$IFEND}
        //2014/7/23 18:23:52 220118016-198-0-14350832-2-0
        if ProcessMsg.wParam = 0 then begin
          if (ProcessMsg.nParam1 < 100) then begin
            m_defMsg := MakeDefaultMsg($00C6,
              Integer(ProcessMsg.BaseObject),
              ProcessMsg.nParam1,
              ProcessMsg.nParam2,
              ProcessMsg.wParam);
            SendSocket(@m_defMsg, '');
          end else
            ClientSplitItem(ProcessMsg.nParam1, ProcessMsg.nParam2, False);
        end else
          ClientSplitItem(ProcessMsg.nParam1, ProcessMsg.nParam2, True);
      end;
    CM_QUERYSLAVER: begin                                                                           //查看宝宝属性
        ClientQuerySlaverState;
      end;
    $9590: begin                                                                                    //刻石头结果
        m_defMsg := MakeDefaultMsg($9590, ProcessMsg.wParam, ProcessMsg.nParam1, 0, 0);
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    CM_GEMCOUNT: begin
        ClientQueryBaoshi;
      end;
    CM_PETEQUIPUP: begin
        ClientPetEquipUp(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam), ProcessMsg.sMsg);
      end;
    CM_GEMCONDENSE: begin                                                                           //宝石凝练    <我要凝炼宝石/@@gemcondense>
        ClientGemItems(ProcessMsg.nParam1, ProcessMsg.wParam, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    CM_ORIGINALSTONE: begin
        ClientOriginalStoneSmelt(ProcessMsg.nParam1, ProcessMsg.wParam, ProcessMsg.nParam2, ProcessMsg.sMsg);
      end;
    CM_GEMSMELT: begin
        ClientGemSmelt(ProcessMsg.wParam, LoByte(ProcessMsg.nParam2), HiByte(ProcessMsg.nParam2), ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    CM_REFINE: begin
        ClientRefineItems(ProcessMsg.nParam2, ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam), ProcessMsg.sMsg);
      end;
    CM_FUSEEQUIP: begin
        ClientfuseequipItem(ProcessMsg.nParam2, ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam), ProcessMsg.sMsg);
      end;
    CM_SENDBLESS: begin
        ClientSendBlessMsg(ProcessMsg.nParam1, ProcessMsg.nParam3, DeCodeString(ProcessMsg.sMsg));
      end;
    RM_MOVEFAIL: begin                                                                              //移动失败
        m_defMsg := MakeDefaultMsg(SM_MOVEFAIL, Integer(Self), m_nCurrX, m_nCurrY, m_btDirection);
        CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
        s1C := EnCodeBuffer(@CharDescEx, SizeOf(CharDescEx));
        nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
        if ProcessMsg.sMsg <> '' then
          s1C := s1C + (EnCodeString(ProcessMsg.sMsg + '/' + IntToStr(nObjCount)));
        SendSocket(@m_defMsg, s1C);
      end;
    RM_LONGHIT: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_LONGHIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_WIDEHIT: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_WIDEHIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_FIREHIT: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_FIREHIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_CRSHIT: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_CRSHIT, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;

    RM_42: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_42, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_43: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_43, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_60: begin
        if TBaseObject(ProcessMsg.BaseObject) <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_60, Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;
      end;
    RM_STRUCK,                                                                                      //有目标被攻击
      RM_STRUCK_MAG,
      RM_STRUCK_NEWMAG1: begin
        if ProcessMsg.nParam1 > 0 then begin
          if (ProcessMsg.BaseObject <> nil) and (TBaseObject(ProcessMsg.BaseObject) = Self) then begin //本人被攻击,处理PK标志等
            if (TBaseObject(ProcessMsg.nParam3) {Attacker} <> nil) then begin
              if TBaseObject(ProcessMsg.nParam3) {Attacker}.m_btRaceServer = RC_PLAYOBJECT then begin //人攻击人
                SetPKFlag(TBaseObject(ProcessMsg.nParam3) {Attacker});
              end;
              SetLastHiter(TBaseObject(ProcessMsg.nParam3) {Attacker});
            end;

            if (g_CastleManager.IsCastleMember(Self) <> nil) and (TBaseObject(ProcessMsg.nParam3) {Attacker} <> nil) then begin
              TBaseObject(ProcessMsg.nParam3) {Attacker}.m_boGuardCanAttack := True;
              TBaseObject(ProcessMsg.nParam3) {Attacker}.m_dwGuardAttackTick := GetTickCount();
            end;

            m_nHealthTick := 0;
            m_nSpellTick := 0;
            Dec(m_nPerHealth);
            Dec(m_nPerSpell);
            m_dwStruckTick := GetTickCount();
          end;
          if ((ProcessMsg.wParam in [ET_FIRERAIN, ET_GODFIRERAIN, ET_EVILFIRERAIN]) or (g_Config.boDisableStruck)) and (ProcessMsg.wIdent <> RM_STRUCK_NEWMAG1) then begin
            //火雨不发送受伤动做
          end else begin
            SendStruckMsg(ProcessMsg.wIdent,
              TBaseObject(ProcessMsg.BaseObject),
              TBaseObject(ProcessMsg.nParam3),
              ProcessMsg.nParam1,
              ProcessMsg.wParam);
          end;
        end;
      end;
    RM_ASSISTSKILL: if not m_boPneuma then begin
        MagicEffect.nMonID := ProcessMsg.nParam1;
        MagicEffect.nX := LoWord(ProcessMsg.nParam3);
        MagicEffect.nY := HiWord(ProcessMsg.nParam3);
        MagicEffect.nType := ProcessMsg.wParam;

        m_defMsg := MakeDefaultMsg(SM_ASSISTSKILL, Integer(ProcessMsg.BaseObject), 0, 0, ProcessMsg.nParam2);
        SendSocket(@m_defMsg, EnCodeBuffer(@MagicEffect, SizeOf(TMagicEffect)));
      end;
    RM_USEBINDLINGFU: begin
        if not m_boPneuma then begin
          m_defMsg := MakeDefaultMsg(SM_USEBINDLINGFU, Integer(ProcessMsg.BaseObject), ProcessMsg.wParam, ProcessMsg.nParam2, ProcessMsg.nParam3);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end;
      end;
    RM_25: begin
        if ProcessMsg.BaseObject <> Self then begin
          m_defMsg := MakeDefaultMsg(SM_25,
            Integer(ProcessMsg.BaseObject),
            LoWord(ProcessMsg.nParam1),
            HiWord(ProcessMsg.nParam1),
            ProcessMsg.wParam);
          NewMagicEff.MagicID := ProcessMsg.nParam2;
          NewMagicEff.ChrStatus := ProcessMsg.nParam3;
          SendSocket(@m_defMsg, EnCodeBuffer(@NewMagicEff, SizeOf(TNewMagicEff)));
        end;
      end;
    RM_DEATH: begin                                                                                 //死亡
        CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
        if ProcessMsg.nParam3 = 1 then begin
          m_defMsg := MakeDefaultMsg(SM_NOWDEATH,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.wParam);
          CharDescEx.Featurex := 0;

          SendSocket(@m_defMsg, EnCodeBuffer(@CharDescEx, 9));
        end else begin
          m_defMsg := MakeDefaultMsg(SM_DEATH,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.wParam);

          s1C := EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx));

          if ProcessMsg.sMsg <> '' then begin
            nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
            sTmp := ProcessMsg.sMsg + '/' + IntToStr(nObjCount) + TBaseObject(ProcessMsg.BaseObject).GetCharTurnMsg;
            s1C := s1C + EnCodeBuffer(@sTmp[1], Length(sTmp));
          end;
          SendSocket(@m_defMsg, s1C);
        end;
      end;
    RM_DISAPPEAR: begin                                                                             //消失
        m_defMsg := MakeDefaultMsg(SM_DISAPPEAR,
          Integer(ProcessMsg.BaseObject),
          TBaseObject(ProcessMsg.BaseObject).m_nCurrX,
          TBaseObject(ProcessMsg.BaseObject).m_nCurrY,
          TBaseObject(ProcessMsg.BaseObject).m_btDirection);
        SendSocket(@m_defMsg, '');
      end;
    RM_SITDOWN: begin                                                                               //上马下马
        m_defMsg := MakeDefaultMsg(SM_SITDOWN, Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam1),
          HiWord(ProcessMsg.nParam1),
          ProcessMsg.wParam);
        if (ProcessMsg.sMsg <> '') then
          SendSocket(@m_defMsg, ProcessMsg.sMsg)                                                    //支持骑战
        else
          SendSocket(@m_defMsg, EnCodeBuffer(@ProcessMsg.nParam2, 4));
      end;
    RM_205: begin                                                                                   //自己发的消息
        m_defMsg := MakeDefaultMsg(SM_205, ProcessMsg.nParam3, 0, 0, 0);
        SendSocket(@m_defMsg, '');
      end;
    RM_PETBAGITEMS: begin
        SendPetBagItems;
      end;
    RM_SKELETON: begin                                                                              //10024 004D8D7B   //被攻击
        m_defMsg := MakeDefaultMsg(SM_SKELETON,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.wParam);
        CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));
        s1C := EnCodeBuffer(@CharDescEx, SizeOf(CharDescEx));

        nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
        if ProcessMsg.sMsg <> '' then
          s1C := s1C + (EnCodeString(ProcessMsg.sMsg + '/' + IntToStr(nObjCount)));
        SendSocket(@m_defMsg, s1C);
      end;
    RM_USERNAME: begin                                                                              //10043 004D9587     //查询用户名
        m_defMsg := MakeDefaultMsg(SM_USERNAME, Integer(ProcessMsg.BaseObject),
          GetCharColor(TBaseObject(ProcessMsg.BaseObject)), 0, 0);
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    RM_WINEXP: begin                                                                                //10044//获得经验
        m_defMsg := MakeDefaultMsg(SM_WINEXP, Integer(m_Abil.Exp), LoWord(ProcessMsg.nParam1), HiWord(ProcessMsg.nParam1), 0);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
        if LongWord(ProcessMsg.nParam1) >= 10000 then begin
          RecalcAbilitys();
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
        end;
      end;
    RM_LEVELUP: begin                                                                               //10045 004D965B    //等级提升
        i := Integer(Self);
        m_defMsg := MakeDefaultMsg(SM_LEVELUP, m_Abil.Exp, _MIN(m_Abil.level, g_Config.nClientShowLevelLimit), LoWord(i), HiWord(i));
        SendSocket(@m_defMsg, EnCodeBuffer(@m_Abil.Exp, 8));                                        //防止客户端在升级后显示英雄榜
        RecalcAbilitys();
        SendUpdateMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
        SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
      end;
    RM_CHANGENAMECOLOR: begin                                                                       //10046 004D9555  //名字颜色改变
        SendDefMessage(SM_CHANGENAMECOLOR,
          Integer(ProcessMsg.BaseObject),
          GetCharColor(TBaseObject(ProcessMsg.BaseObject)),
          0,
          0,
          '');
      end;
    RM_LOGON: begin                                                                                 //10050            //登陆
        if m_PEnvir.m_MapFlag.boDARK then nObjCount := 1
        else begin
          case m_nBright of
            1: nObjCount := 0;
            3: nObjCount := 1;
          else nObjCount := 1;
          end;
        end;
        if m_PEnvir.m_MapFlag.boDAY then nObjCount := 0;
        SendLogon();
        ClientQueryUserName(Self, m_nCurrX, m_nCurrY);
        RefUserState();
        SendMapDescription();
        nObjCount := 1;
        SendDefMessage(SM_VERSION_FAIL, $FFFFFFFFF2D505D7, 0, 0, 0, '');
      end;
    RM_HEAR,
      RM_WHISPER,
      RM_CRY,
      RM_SYSMESSAGE,
      RM_GROUPMESSAGE,
      RM_SYSMESSAGE2,
      RM_GUILDMESSAGE,
      RM_SYSMESSAGE3,
      RM_MERCHANTSAY,
      RM_TITLEMSM,
      RM_CLANMESSAGE,
      RM_COLORTASKSAY:
      begin
        case ProcessMsg.wIdent of
          RM_HEAR: m_defMsg := MakeDefaultMsg(SM_HEAR,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              ProcessMsg.nParam3);                                                                  //10030
          RM_WHISPER: m_defMsg := MakeDefaultMsg(SM_WHISPER,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              ProcessMsg.wParam);                                                                   //10031
          RM_CRY: m_defMsg := MakeDefaultMsg(SM_HEAR,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              1);                                                                                   //10032
          RM_SYSMESSAGE: m_defMsg := MakeDefaultMsg(SM_SYSMESSAGE,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              1);                                                                                   //10100 红色
          RM_GROUPMESSAGE: m_defMsg := MakeDefaultMsg(SM_SYSMESSAGE,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              1);                                                                                   //10102
          RM_GUILDMESSAGE: m_defMsg := MakeDefaultMsg(SM_GUILDMESSAGE,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              1);                                                                                   //10104
          RM_MERCHANTSAY: m_defMsg := MakeDefaultMsg(SM_MERCHANTSAY,
              Integer(ProcessMsg.BaseObject),
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              ProcessMsg.nParam3,
              1);                                                                                   //10126
          RM_TITLEMSM: m_defMsg := MakeDefaultMsg(SM_SYSMESSAGE,
              Integer(ProcessMsg.BaseObject),
              ProcessMsg.nParam1,
              ProcessMsg.nParam2,
              ProcessMsg.nParam3);
          RM_CLANMESSAGE: m_defMsg := MakeDefaultMsg(SM_CLANMESSAGE,
              1,
              MakeWord(ProcessMsg.nParam1, ProcessMsg.nParam2),
              0,
              0);
          RM_COLORTASKSAY: m_defMsg := MakeDefaultMsg(CM_COLORTASKSAY,
              Integer(ProcessMsg.BaseObject),
              0,
              0,
              ProcessMsg.wParam);
        end;
        if not m_boPneuma or (ProcessMsg.wIdent = RM_SYSMESSAGE) then
          //2006/7/12 防止元神听到说话内容而出现消息重复
          SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    RM_FLYMSG: if not m_boPneuma then begin
        m_defMsg := MakeDefaultMsg(SM_FLYMSG, 0, ProcessMsg.wParam, 0,
          MakeWord(0, ProcessMsg.nParam1));
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    RM_510: begin
        m_defMsg := MakeDefaultMsg(SM_510, Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2);
        SendSocket(@m_defMsg, EnCodeString(ProcessMsg.sMsg));
      end;
    RM_SENDBAGSIZE: begin
        SendDefMessage(SM_BAGSIZE, Integer(Self), 0, m_nBagSize, 0, '');
      end;
    RM_ABILITY: begin
        ClientQueryAbility();
      end;
    RM_HIDE: begin
        m_defMsg := MakeDefaultMsg(SM_HIDE,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3);
        SendSocket(@m_defMsg, '');
      end;
    RM_DAYCHANGING: begin                                                                           //10053
        m_defMsg := MakeDefaultMsg(SM_DAYCHANGING, $FFFFFFFF, m_nBright,
          m_PEnvir.m_MapFlag.nWeather, m_PEnvir.m_MapFlag.wWindSpeed);
        nObjCount := m_PEnvir.m_MapFlag.dwWindColor;
        SendSocket(@m_defMsg, EnCodeBuffer(@nObjCount, SizeOf(Integer)));
      end;
    RM_FIREBURN: begin
        m_defMsg := MakeDefaultMsg(SM_FireBurn,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam1),
          HiWord(ProcessMsg.nParam1),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_ITEMSHOW: begin
        if pTMapItem(ProcessMsg.nParam1).UserItem.btItemExt[29] > 0 then                            //新增支持掉落物品名字颜色
        begin
          g_SmallPacketManage.Init();
          g_SmallPacketManage.WriteString(ProcessMsg.sMsg, 4);
          g_SmallPacketManage.WriteByte(0);
          g_SmallPacketManage.WriteByte(pTMapItem(ProcessMsg.nParam1).UserItem.btItemExt[29]);
          SendDefMessage(SM_ITEMSHOW,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.wParam,
            g_SmallPacketManage.GetMsg, True);
        end else begin
          SendDefMessage(SM_ITEMSHOW,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.wParam,
            ProcessMsg.sMsg);
        end;
        UpdateVisibleItem(ProcessMsg.nParam2, ProcessMsg.nParam3, pTMapItem(ProcessMsg.nParam1));
      end;
    RM_ITEMHIDE: begin
        SendDefMessage(SM_ITEMHIDE,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          0,
          '');
      end;
    RM_DOOROPEN: begin                                                                              //10112 004D9D6A
        SendDefMessage(SM_OPENDOOR_OK,
          0,
          ProcessMsg.nParam1,                                                                       {x}
          ProcessMsg.nParam2,                                                                       {y}
          0,
          '');
      end;
    RM_DOORCLOSE: begin                                                                             //10113 004D9D8A
        SendDefMessage(SM_CLOSEDOOR,
          0,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          '');
      end;
    RM_SENDUSEITEMS: begin
        SendUseitems();
        SendEntopticItems;
        SendTigerItem();
      end;
    RM_QUERYPETSOUL: begin
        //检测摆摊灵兽、凤凰探宝、魂佑附体
        CheckPackPetShop();
        ClientQueryPetSoulInfo;                                                                     //发送魂佑灵兽信息
      end;
    CM_QUERYPETSOULITEM: begin
        ClientQueryPetSoulItem(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    RM_WEIGHTCHANGED: begin                                                                         //10115 004D9DC4
        SendDefMessage(SM_WEIGHTCHANGED,
          m_WAbil.Weight,
          m_WAbil.WearWeight,
          m_WAbil.HandWeight,
          0,
          '');
      end;
    RM_FEATURECHANGED: begin                                                                        //10116
        //        if ProcessMsg.BaseObject <> Self then begin
        m_defMsg := MakeDefaultMsg(SM_FEATURECHANGED,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam1),
          HiWord(ProcessMsg.nParam1),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
        //         end;
      end;
    RM_CLEAROBJECTS: begin                                                                          //10117
        SendDefMessage(SM_CLEAROBJECTS,
          0,
          0,
          0,
          0,
          '');
      end;
    RM_CHANGEMAP: begin
        try
          if m_PEnvir = nil then begin
            MainOutMessage(sHint5);
            Exit;
          end;

          SendDefMessage(SM_CHANGEMAP, Integer(Self), m_nCurrX, m_nCurrY, 10240 {m_btDirection}, ProcessMsg.sMsg);

          RefUserState();
          SendMapDescription();
          SendMsg(Self, RM_DAYCHANGING, 0, 0, 0, 0, '');

          if ProcessMsg.wParam = 0 then begin                                                       //过地图,下马
            if not CheckMapRideOn(m_PEnvir) then ClientRideOff;

            if not m_PEnvir.m_MapFlag.boCanReCallEvil then begin                                    //不允许带心魔
              ClearEvilFollower(6);
            end;
            //雪莲过地图失效
            if g_Config.boChMapSaussureaFail then begin
              if m_nSuperIncHealth > 0 then begin
                SendMsg(Self, RM_510, 0, 0, 1, 0, '');
                m_nSuperIncHealth := 0;
              end;
              if m_nSuperIncSpell > 0 then begin
                m_nSuperIncSpell := 0;
                SendMsg(Self, RM_510, 0, 0, 2, 0, '');
              end;
            end;
          end;
          if m_Pet <> nil then begin
            m_Pet.m_nTargetX := -1;
            m_Pet.m_nTargetY := -1;
          end;
          m_nPetTargetX := -1;
          m_nPetTargetY := -1;

        except
        end;
      end;
    RM_BUTCH: begin                                                                                 //10119
        if ProcessMsg.BaseObject <> nil then begin
          m_defMsg := MakeDefaultMsg(SM_BUTCH,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.wParam);
          SendSocket(@m_defMsg, '');
        end;

      end;
    RM_MAGICFIRE: begin
        m_defMsg := MakeDefaultMsg(SM_MAGICFIRE,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,                                                                       //x
          ProcessMsg.nParam2,                                                                       //y
          ProcessMsg.wParam);                                                                       //Effect
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_MAGICFIREFAIL: begin                                                                         //10121
        SendDefMessage(SM_MAGICFIRE_FAIL, Integer(ProcessMsg.BaseObject), 0, 0,
          0, '');
      end;
    RM_SENDMYMAGIC: SendUseMagic();                                                                 //10122
    RM_MAGIC_LVEXP: begin                                                                           //10123
        SendDefMessage(SM_MAGIC_LVEXP,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          LoWord(ProcessMsg.nParam3),
          HiWord(ProcessMsg.nParam3),
          '');
      end;
    RM_DURACHANGE: begin                                                                            //10125
        SendDefMessage(SM_DURACHANGE,
          ProcessMsg.nParam1,
          ProcessMsg.wParam,
          LoWord(ProcessMsg.nParam2),
          HiWord(ProcessMsg.nParam2),
          '');
      end;
    RM_MERCHANTDLGCLOSE: begin                                                                      //10127
        if ProcessMsg.wParam = 0 then
          SendDefMessage(SM_MERCHANTDLGCLOSE,
            ProcessMsg.nParam1,
            0,
            0,
            0,
            '')
        else
          SendDefMessage(SM_KAITIANTOWERCLOSE,
            ProcessMsg.nParam1,
            0,
            0,
            0,
            '')
      end;
    RM_SENDGOODSLIST: begin
        if ProcessMsg.nParam3 = 1 then begin
          m_defMsg := MakeDefaultMsg(3039, ProcessMsg.nParam1, ProcessMsg.nParam2, 0, 0);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end else if ProcessMsg.nParam3 = 2 then begin
          m_defMsg := MakeDefaultMsg(3039, ProcessMsg.nParam1, ProcessMsg.nParam2, 5, 0);
          SendSocket(@m_defMsg, ProcessMsg.sMsg);
        end else
          SendDefMessage(SM_SENDGOODSLIST, ProcessMsg.nParam1, ProcessMsg.nParam2, 0, ProcessMsg.wParam, ProcessMsg.sMsg);
      end;
    RM_SENDINGOTGOODSLIST: begin
        SendDefMessage(SM_SENDINGOTGOODSLIST,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          0,
          ProcessMsg.sMsg);
      end;
    RM_SENDUSERSELL: begin                                                                          //10129
        SendDefMessage(SM_SENDUSERSELL,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          0,
          ProcessMsg.sMsg);
      end;
    RM_SENDBUYPRICE: begin                                                                          //10130  004D9BAB
        SendDefMessage(SM_SENDBUYPRICE,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_USERSELLITEM_OK: begin                                                                       //10131  004D9BC8
        SendDefMessage(SM_USERSELLITEM_OK,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_USERSELLITEM_FAIL: begin                                                                     //10132  004D9BC8
        SendDefMessage(SM_USERSELLITEM_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_BUYITEM_SUCCESS: begin                                                                       //10133  004D9C02
        SendDefMessage(SM_BUYITEM_SUCCESS,
          ProcessMsg.nParam1,
          LoWord(ProcessMsg.nParam2),
          HiWord(ProcessMsg.nParam2),
          0,
          '');
      end;
    RM_BUYITEM_FAIL: begin                                                                          //10134  004D9C2C
        SendDefMessage(SM_BUYITEM_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_SENDDETAILGOODSLIST: begin                                                                   //10135  004D9C83
        m_defMsg := MakeDefaultMsg(SM_SENDDETAILGOODSLIST,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_GOLDCHANGED: begin                                                                           //10136
        SendDefMessage(SM_GOLDCHANGED,
          ProcessMsg.nParam1,
          ProcessMsg.wParam,
          0,
          0,
          '');
      end;
    RM_GAMEGOLDCHANGED: begin
        SendDefMessage(SM_GAMEGOLDCHANGED,
          ProcessMsg.nParam1,
          ProcessMsg.wParam,
          0,
          0,
          '');
      end;
    RM_GUILDGOLDCHANGED: begin
        SendDefMessage(SM_GUILDGOLDCHANGED,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_COLLECTPOINT: begin
        if m_nCollectPoint > 0 then
          SendDefMessage(SM_COLLECTPOINT, m_nCollectPoint, 0, 0, 0, '');
      end;
    RM_LAMPCHANGEDURA: begin                                                                        //10138
        SendDefMessage(SM_LAMPCHANGEDURA,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_CHARSTATUSCHANGED: begin
        m_defMsg := MakeDefaultMsg(SM_CHARSTATUSCHANGED,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam1),
          HiWord(ProcessMsg.nParam1),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_FENGHAO: begin                                                                               //是否显示翅膀
        SendDefMessage(SM_FENGHAO,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.sMsg);
      end;
    RM_GROUPCANCEL: begin                                                                           //10140 004D9F28
        SendDefMessage(SM_GROUPCANCEL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_SENDUSERREPAIR,
      RM_SENDUSERSREPAIR: begin                                                                     //10141 004D9B3C
        SendDefMessage(SM_SENDUSERREPAIR,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          0,
          '');
      end;
    RM_USERREPAIRITEM_OK: begin                                                                     //10143  004D9CA6
        SendDefMessage(SM_USERREPAIRITEM_OK,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          0,
          '');
      end;
    RM_SENDREPAIRCOST: begin                                                                        //10142  004D9CE4
        if ProcessMsg.wParam <> 0 then
          SendDefMessage(SM_SENDREPAIRCOST,
            ProcessMsg.nParam1,
            10 + ProcessMsg.wParam,
            0,
            0,
            '')
        else
          SendDefMessage(SM_SENDREPAIRCOST,
            ProcessMsg.nParam1,
            0,
            0,
            0,
            '');
      end;
    RM_USERREPAIRITEM_FAIL: begin                                                                   //10144  004D9CC7
        SendDefMessage(SM_USERREPAIRITEM_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_USERSTORAGEITEM: begin                                                                       //10146  004D9B5B
        SendDefMessage(SM_SENDUSERSTORAGEITEM,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          0,
          '');
      end;
    RM_USERGETBACKITEM: begin                                                                       //10147  SM_SAVEITEMLIST
        SendSaveItemList(ProcessMsg.nParam1, ProcessMsg.wParam = 1);
      end;
    RM_SENDDELITEMLIST: begin                                                                       //10148  SM_DELITEMS
        SendDelItemList(TStringList(ProcessMsg.nParam1));
        TStringList(ProcessMsg.nParam1).free;
      end;
    RM_USERMAKEDRUGITEMLIST: begin                                                                  //10149
        SendDefMessage(SM_SENDUSERMAKEDRUGITEMLIST,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0,
          0,
          ProcessMsg.sMsg);
      end;
    RM_MAKEDRUG_SUCCESS: begin                                                                      //10150 004D9C49
        SendDefMessage(SM_MAKEDRUG_SUCCESS,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_MAKEDRUG_FAIL: begin                                                                         //10151 004D9C66
        SendDefMessage(SM_MAKEDRUG_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_ALIVE: begin                                                                                 //10153 004D8E09
        m_defMsg := MakeDefaultMsg(SM_ALIVE,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.wParam);

        CharDescEx.Feature :=
          TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));

        SendSocket(@m_defMsg, EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx)));
      end;
    RM_DIGUP: begin                                                                                 //10200 004D91B4
        m_defMsg := MakeDefaultMsg(SM_DIGUP,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          MakeWord(ProcessMsg.wParam,
          TBaseObject(ProcessMsg.BaseObject).m_btGender));
        MessageBodyWL.lParam1 := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        MessageBodyWL.lParam2 := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        MessageBodyWL.lTag1 := ProcessMsg.nParam3;
        MessageBodyWL.lTag2 := 0;
        s1C := EnCodeBuffer(@MessageBodyWL, SizeOf(TMessageBodyWL));
        SendSocket(@m_defMsg, s1C);
      end;
    RM_DIGDOWN: begin                                                                               //10201 004D9254
        m_defMsg := MakeDefaultMsg(SM_DIGDOWN,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          0);
        SendSocket(@m_defMsg, '');
      end;
    RM_FLYAXE: begin                                                                                //10202 004D9358
        if TBaseObject(ProcessMsg.nParam3) <> nil then begin
          MessageBodyW.Param1 := TBaseObject(ProcessMsg.nParam3).m_nCurrX;
          MessageBodyW.Param2 := TBaseObject(ProcessMsg.nParam3).m_nCurrY;
          MessageBodyW.Tag1 := LoWord(ProcessMsg.nParam3);
          MessageBodyW.Tag2 := HiWord(ProcessMsg.nParam3);
          m_defMsg := MakeDefaultMsg(SM_FLYAXE,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.wParam);
          SendSocket(@m_defMsg, EnCodeBuffer(@MessageBodyW, SizeOf(TMessageBodyW)));
        end;
      end;
    RM_2BDC: begin                                                                                  //魔眼攻击
        if TBaseObject(ProcessMsg.nParam3) <> nil then begin
          m_defMsg := MakeDefaultMsg($2BDC,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,                                                                     //X
            ProcessMsg.nParam2,                                                                     //Y
            ProcessMsg.wParam);                                                                     //Dir
          nObjCount := ProcessMsg.nParam3;
          SendSocket(@m_defMsg, EnCodeBuffer(@nObjCount, SizeOf(Integer)));
        end;
      end;
    RM_LIGHTING: begin                                                                              //10204 004D93FD
        if TBaseObject(ProcessMsg.nParam3) <> nil then begin
          MessageBodyWL.lParam1 := TBaseObject(ProcessMsg.nParam3).m_nCurrX;
          MessageBodyWL.lParam2 := TBaseObject(ProcessMsg.nParam3).m_nCurrY;
          MessageBodyWL.lTag1 := ProcessMsg.nParam3;
          MessageBodyWL.lTag2 := ProcessMsg.wParam;
          m_defMsg := MakeDefaultMsg(SM_LIGHTING,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            TBaseObject(ProcessMsg.BaseObject).m_btDirection);
          SendSocket(@m_defMsg, EnCodeBuffer(@MessageBodyWL,
            SizeOf(TMessageBodyWL)));
        end;
      end;
    RM_10205: begin                                                                                 //10205 004D949A
        SendDefMessage(SM_716,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1 {x},
          ProcessMsg.nParam2 {y},
          ProcessMsg.nParam3 {type},
          '');
      end;
    RM_CHANGEGUILDNAME: begin
        SendChangeGuildName();
      end;
    RM_TAKEON2: begin
        SendDefMessage(SM_TAKEON2, ProcessMsg.nParam1, ProcessMsg.wParam, 0, 0, '');
      end;
    RM_SUBABILITY: begin
        QuerySubAbility();
      end;
    RM_BUILDGUILD_OK: begin                                                                         //10303 004D9F51
        SendDefMessage(SM_BUILDGUILD_OK,
          0,
          0,
          0,
          0,
          '');
      end;
    RM_BUILDGUILD_FAIL: begin                                                                       //10304 004D9F6D
        SendDefMessage(SM_BUILDGUILD_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_DONATE_OK: begin                                                                             //10305 004D9FA7
        SendDefMessage(SM_DONATE_OK,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_DONATE_FAIL: begin                                                                           //10306 004D9F8A
        SendDefMessage(SM_DONATE_FAIL,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          '');
      end;
    RM_MYSTATUS: begin
        SendDefMessage(SM_MYSTATUS, 0, GetMyStatus, 0, 0, '');
      end;
    RM_MENU_OK: begin                                                                               //10309  004D9FC4
        SendDefMessage(SM_MENU_OK,
          ProcessMsg.nParam1,
          0,
          0,
          0,
          ProcessMsg.sMsg);
      end;
    RM_SPACEMOVE_FIRE,
      RM_SPACEMOVE_FIRE2: begin                                                                     //10330
        if ProcessMsg.wIdent = RM_SPACEMOVE_FIRE then begin
          m_defMsg := MakeDefaultMsg(SM_SPACEMOVE_HIDE,
            Integer(ProcessMsg.BaseObject),
            0,
            0,
            0);
        end else begin
          m_defMsg := MakeDefaultMsg(SM_SPACEMOVE_HIDE2,
            Integer(ProcessMsg.BaseObject),
            0,
            0,
            0);
        end;
        SendSocket(@m_defMsg, '');
      end;
    RM_SPACEMOVE_SHOW,
      RM_SPACEMOVE_SHOW2: begin
        if ProcessMsg.wIdent = RM_SPACEMOVE_SHOW then begin
          m_defMsg := MakeDefaultMsg(SM_SPACEMOVE_SHOW,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            MakeWord(ProcessMsg.wParam,
            TBaseObject(ProcessMsg.BaseObject).m_btGender));
        end else begin
          m_defMsg := MakeDefaultMsg(SM_SPACEMOVE_SHOW2,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            MakeWord(ProcessMsg.wParam,
            TBaseObject(ProcessMsg.BaseObject).m_btGender));
        end;
        CharDescEx.Feature := TBaseObject(ProcessMsg.BaseObject).GetFeature(Self);
        CharDescEx.Status := TBaseObject(ProcessMsg.BaseObject).m_nCharStatus;
        CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));

        s1C := EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx));
        nObjCount := GetCharColor(TBaseObject(ProcessMsg.BaseObject));
        if ProcessMsg.sMsg <> '' then begin
          s1C := s1C + EnCodeString(ProcessMsg.sMsg + '/' +
            IntToStr(nObjCount));
        end;
        SendSocket(@m_defMsg, s1C);
      end;
    RM_RECONNECTION: begin                                                                          //10332
        m_boReconnection := True;
        SendDefMessage(SM_RECONNECT, 0, 0, 0, 0, ProcessMsg.sMsg);
      end;
    RM_HIDEEVENT: begin                                                                             //10333
        SendDefMessage(SM_HIDEEVENT,
          ProcessMsg.nParam1,
          ProcessMsg.wParam,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          '');
      end;
    RM_SHOWEVENT: begin                                                                             //10334
        MessageBodyW.Param1 := HiWord(ProcessMsg.nParam2);
        MessageBodyW.Param2 := 0;
        MessageBodyW.Tag1 := 0;
        MessageBodyW.Tag2 := 0;
        m_defMsg := MakeDefaultMsg(SM_SHOWEVENT,
          ProcessMsg.nParam1,                                                                       //对象ID
          ProcessMsg.wParam,                                                                        //MapEvent.m_nEventType
          LoWord(ProcessMsg.nParam2),                                                               //X
          ProcessMsg.nParam3);                                                                      //Y
        SendSocket(@m_defMsg, EnCodeBuffer(@MessageBodyW,
          SizeOf(TMessageBodyW)));
      end;
    RM_ADJUST_BONUS: begin
        SendAdjustBonus();
      end;
    RM_10401: begin
        ChangeServerMakeSlave(pTSlaveInfo(ProcessMsg.nParam1));
        Dispose(pTSlaveInfo(ProcessMsg.nParam1));
      end;
    RM_FUSHEN: begin
        SendDefMessage(SM_FUSHEN,
          Integer(ProcessMsg.BaseObject),
          HiWord(ProcessMsg.nParam1),
          LoWord(ProcessMsg.nParam1),
          ProcessMsg.wParam,
          '');
      end;
    RM_BREAKWEAPON: begin                                                                           //10413
        SendDefMessage(SM_BREAKWEAPON,
          Integer(ProcessMsg.BaseObject),
          0,
          0,
          0,
          '');
      end;
    RM_INSTANCEHEALGUAGE: begin                                                                     //10414
        if (ProcessMsg.BaseObject = Self) then
          SendDefMessage(SM_INSTANCEHEALGUAGE,
            Integer(ProcessMsg.BaseObject),
            TBaseObject(ProcessMsg.BaseObject).m_WAbil.dwHP,
            TBaseObject(ProcessMsg.BaseObject).m_WAbil.dwMaxHP,
            0,
            '')
        else
          SendDefMessage(SM_INSTANCEHEALGUAGE,
            Integer(ProcessMsg.BaseObject),
            CalcCent(TBaseObject(ProcessMsg.BaseObject).m_WAbil.dwHP,
            TBaseObject(ProcessMsg.BaseObject).m_WAbil.dwMaxHP),
            TBaseObject(ProcessMsg.BaseObject).m_wMaxHPCent,
            0,
            '');

      end;
    RM_CHANGEFACE: begin                                                                            //10415
        if (ProcessMsg.nParam1 <> 0) and (ProcessMsg.nParam2 <> 0) then begin
          m_defMsg := MakeDefaultMsg(SM_CHANGEFACE,
            ProcessMsg.nParam1,
            LoWord(ProcessMsg.nParam2),
            HiWord(ProcessMsg.nParam2),
            0);
          CharDescEx.Feature := TBaseObject(ProcessMsg.nParam2).GetFeature(Self);
          CharDescEx.Status := TBaseObject(ProcessMsg.nParam2).m_nCharStatus;
          CharDescEx.Featurex := GetMaxHPCent(TBaseObject(ProcessMsg.BaseObject));

          SendSocket(@m_defMsg, EnCodeBuffer(@CharDescEx, SizeOf(TCharDescEx)));
        end;
      end;
    RM_PASSWORD: begin                                                                              //10416 004D9FE3
        SendDefMessage(SM_PASSWORD,
          0,
          0,
          0,
          0,
          '');
      end;
    RM_PLAYDICE: begin                                                                              //10500 004D9FFF
        MessageBodyWL.lParam1 := ProcessMsg.nParam1;
        MessageBodyWL.lParam2 := ProcessMsg.nParam2;
        MessageBodyWL.lTag1 := ProcessMsg.nParam3;

        m_defMsg := MakeDefaultMsg(SM_PLAYDICE,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam,
          0,
          0);
        SendSocket(@m_defMsg, EnCodeBuffer(@MessageBodyWL,
          SizeOf(TMessageBodyWL)) + EnCodeString(ProcessMsg.sMsg));
      end;
    RM_PASSWORDSTATUS: begin
        m_defMsg := MakeDefaultMsg(SM_PASSWORDSTATUS,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_GHOST: begin
        m_defMsg := MakeDefaultMsg(SM_GHOST, Integer(ProcessMsg.BaseObject),
          ProcessMsg.wParam, 0, 0);
        SendSocket(@m_defMsg, EnCodeBuffer(@ProcessMsg.nParam1,
          SizeOf(Integer)));
      end;
    CM_CALCELTASK: begin
        ClientDelTask(ProcessMsg.nParam1);
      end;
    RM_ADDTASK: begin
        SendDefMessage(SM_TASKINFO, ProcessMsg.nParam1, ProcessMsg.nParam2, 0, ProcessMsg.wParam, ProcessMsg.sMsg);
        SendDefMessage(SM_TASKINFO, 0, 0, 0, 0, Format(sTaskInfo, [m_nMaxTaskCount, m_nAchievement, m_nTaskCount]));
      end;
    RM_YSSKILL: begin
        m_defMsg := MakeDefaultMsg(SM_YSSKILL,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam2),                                                               //60
          HiWord(ProcessMsg.nParam2),                                                               //15
          0);                                                                                       //1
        CombineSkillEffect.nMonID := ProcessMsg.nParam1;
        CombineSkillEffect.nSkillType := 0;
        CombineSkillEffect.nPneumaID := ProcessMsg.nParam3;
        s1C := EnCodeBuffer(@CombineSkillEffect, SizeOf(TCombineSkillEffect));

        SendSocket(@m_defMsg, s1C);
      end;
    RM_CHAINTHUNDER: begin
        m_defMsg := MakeDefaultMsg(SM_CHAINTHUNDER,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam2),
          HiWord(ProcessMsg.nParam2),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_TOWERAAILITY: begin
        SendGuildTowerInfo();
      end;
    RM_PROWL: begin
        m_nCharStatus := GetCharStatus();
        StatusChanged();
        SendRefMsg(RM_DISAPPEAR, 0, 0, 0, 0, '');
        m_boObMode := True;
      end;
    CM_CATCHEVIL: begin                                                                             //俘获心魔
        ClientCatchEvil(TBaseObject(ProcessMsg.nParam1),
          MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    CM_ADDEVILTOITEM: begin                                                                         //附魔到装备
        ClientAddEvilToItem(ProcessMsg.wParam, ProcessMsg.nParam1,
          MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    CM_ADDANTIEVILPOWER: begin                                                                      //增加镇魔值
        ClientAddAntiEvilPower(ProcessMsg.wParam, ProcessMsg.nParam1,
          MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    $889B: begin                                                                                    //书页
        ExecuteScript(g_ManageNPC, '@ReadBook' + IntToStr(ProcessMsg.nParam2));
      end;
    $5EB6: begin                                                                                    //收起元神
        if m_boPneuma and (m_PneumaObject <> nil) then begin
          TPlayObject(m_PneumaObject).PneumaLogin();                                                //24246     下线元神
        end;
{$IF USESDK = DEBUG}
        MainOutMessage(Format('元神消息:%s-%d-%d-%d-%d-%d %s-%S',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)]));
{$IFEND}
      end;
    $5EB7: begin                                                                                    //释放元神
        if m_boPneuma and (m_PneumaObject <> nil) then begin
          TPlayObject(m_PneumaObject).PneumaLogin();                                                //24246     下线元神
        end;
{$IF USESDK = DEBUG}
        MainOutMessage(Format('元神消息:%s-%d-%d-%d-%d-%d %s-%S',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)]));
{$IFEND}
      end;
    CM_ITEMPIC: begin
        SendScriptItemPic(ProcessMsg.sMsg, ProcessMsg.nParam2);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('精彩活动:%s-%d-%d-%d-%d-%d %s-%S',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)]));
{$IFEND}
      end;
    CM_REQUESTMASTER: begin                                                                         //784-0-233480192-1-0   1 招收徒弟 2 请求拜师
        ClientRequest(ProcessMsg.wIdent, ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    CM_REQUESTDEAL: begin                                                                           //786-0-232991184-1-0
        ClientRequest(ProcessMsg.wIdent, ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    CM_EVOLUTION: begin
        DeCodeBuffer(ProcessMsg.sMsg, @nObjCount, SizeOf(nObjCount));
        ClientEvoluTion(ProcessMsg.wParam, ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), nObjCount);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('幻化消息:%d-%d-%d-%d-%d %s-%d',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg, nObjCount]));
{$IFEND}
      end;
    $0334: begin
        ExecuteScript(g_ManageNPC, '@离开迷仙阵');
{$IF USESDK = DEBUG}
        MainOutMessage(Format('迷仙阵消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    $9555: begin
        if m_PEnvir.m_MapFlag.boCanReLive then begin
          m_sScriptParam[0] := m_sMapName;
          ExecuteScript(g_ManageNPC, '@原地复活');
        end;
{$IF USESDK = DEBUG}
        ReAlive;
        SendRefMsg(RM_510, 1, 0, 71, 0, '');
{$IFEND}
      end;
    SM_QUERYRELIVE: begin                                                                           //        涅槃重生技能询问复活
        if m_boQueryReLive then begin
          m_boQueryReLive := False;
          ReAlive;
          n18 := Round(m_WAbil.dwMaxHP / 3);
          Inc(m_nIncHealth, n18);
          n18 := m_WAbil.dwMaxHP - n18;
          IncHealthSpell(n18, 10);
          //m_WAbil.HP := m_WAbil.MaxHP;
          RecalcAbilitys();
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
          SendDefMessage($9555, Integer(Self), 0, 0, 1, '');
          SendRefMsg(RM_510, 1, 0, 130, 0, '');
        end;
      end;
    $033B: begin
        case ProcessMsg.nParam2 of
          1: ExecuteScript(g_ManageNPC, '@扩展包裹');
          2: ExecuteScript(g_ManageNPC, '@扩展钱袋');
          3: ExecuteScript(g_ManageNPC, '@扩展元神包裹');
          4, 5: ExecuteScript(g_ManageNPC, '@扩展仓库');
          6: ExecuteScript(g_ManageNPC, '@扩展灵兽包裹');
          7: ExecuteScript(g_ManageNPC, '@_VIP_扩展包裹');
          8: ExecuteScript(g_ManageNPC, '@_VIP_扩展仓库');
        end;
      end;
    CM_TREASUREBOX: begin
        case LoByte(ProcessMsg.nParam2) of
          1: ClientActivationTreasureBox();
          2: ClientEnlargeTreasureBox();
          3: ClientUPGradeTreasureBox(HiByte(ProcessMsg.nParam2), ProcessMsg.sMsg);
          4: ClientInjectPowerToTreasureBox(ProcessMsg.wParam);
          5: ClientTakeItemOutTreasureBox(ProcessMsg.nParam1);
          6: ClientTakeItemToTreasureBox(ProcessMsg.nParam1);
          7: begin
              if (m_TreasureBoxItem = nil) or (m_TreasureBoxItem.DuraMax >= 20) then Exit;
              SendDefMessage(CM_TREASUREBOX, 10, 7, 0, 0, '');
            end;
        end;
{$IF USESDK = DEBUG}
        MainOutMessage(Format('灵犀宝盒消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    CM_TIGEREAT: begin
        m_sScriptParam[0] := IntToStr(ProcessMsg.nParam1);
        ExecuteScript(g_ManageNPC, '@虎王喂食');
      end;
    CM_CALLTIGER: begin
        ClientCallTiger();
      end;
    CM_RECALLTIGER: begin
        ClientReCallTiger();
      end;
    CM_TIGERATTACK: begin
        ClientSetTigerTarget(ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.wParam);
      end;
    SM_ALLOTGUILDGOLD: begin
        ClientAllotGuildGold(DeCodeString(ProcessMsg.sMsg), ProcessMsg.nParam1);
      end;
    RM_BUILDGUILDTOWER: begin
        SendDefMessage(SM_BUILDGUILDTOWER,
          0,
          0,
          0,
          0,
          ProcessMsg.sMsg);
      end;
    SM_BUILDGUILDTOWER: begin
        sTmp := m_PEnvir.GetGuildTowerInfo;
        if sTmp <> '' then begin
          SendDefMessage(SM_BUILDGUILDTOWER, 0, 0, 0, 0, sTmp);
        end;
      end;
    SM_GUILDMEMBERLIST: ClientGuildMemberList();
    SM_GUILDOFFICIALPLAYER: SendNearbyGuildMemberList();
    SM_GUILDOFFICIAL: begin
        case ProcessMsg.nParam3 of
          1: ClientAskForGuildOfficial(ProcessMsg.nParam2, DeCodeString(ProcessMsg.sMsg));
        end;
      end;
    SM_QUESTGUILDOFFICIAL: begin
        ClientGuildOfficial(ProcessMsg.nParam3, ProcessMsg.nParam2, DeCodeString(ProcessMsg.sMsg));
      end;
    SM_TREASUREPAVILION: begin
{$IF USESDK = DEBUG}
        MainOutMessage(Format('珍宝阁消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        case LoByte(ProcessMsg.nParam2) of
          0: begin
              SendTreasurePavilion();
            end;
          1: begin
              m_sScriptParam[0] := IntToStr(HiByte(ProcessMsg.nParam2));
              ExecuteScript(g_GuildTowerNPC, '@珍宝阁开宝');
            end;
          2: begin                                                                                  //极品阁
              SendNonSuchPavilion(HiByte(ProcessMsg.nParam2));
            end;
          3: begin
              if not m_boInNonSuchPavilion then Exit;                                               //没有进入极品阁
              m_sScriptParam[0] := IntToStr(HiByte(ProcessMsg.nParam2));
              ExecuteScript(g_GuildTowerNPC, '@极品阁开宝');
            end;
        end;
      end;
    SM_GUILDTOWER: begin
{$IF USESDK = DEBUG}
        MainOutMessage(Format('通灵塔消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        case ProcessMsg.nParam1 of
          0: begin
              SendGuildTowerRes();
            end;
          1: begin                                                                                  //捐献资源
              FillChar(nArrItem, SizeOf(Integer) * 3, #0);
              DeCodeBuffer(ProcessMsg.sMsg, @nArrItem, SizeOf(Integer) * 3);
              m_sScriptParam[0] := IntToStr(nArrItem[0]);
              m_sScriptParam[1] := IntToStr(nArrItem[1]);
              m_sScriptParam[2] := IntToStr(nArrItem[2]);
              ExecuteScript(g_GuildTowerNPC, '@Contribute');
            end;
        end;
      end;
    RM_LOTUSINFO: begin
        SendDefMessage(SM_LOTUSINFO,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam,
          ProcessMsg.sMsg);
        if ProcessMsg.nParam1 = 0 then                                                              //删除的,多发一次
          SendDefMessage(SM_LOTUSINFO,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.wParam,
            ProcessMsg.sMsg);
      end;
    SM_LOTUSINFO: begin
        ClientQueryMapLotusInfo();
      end;
    $0352: begin
        m_sScriptParam[0] := IntToStr(ProcessMsg.nParam1);
        m_sScriptParam[1] := IntToStr(MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam));
        DeCodeBuffer(ProcessMsg.sMsg, @nObjCount, SizeOf(Integer));
        m_sScriptParam[2] := IntToStr(nObjCount);
        ExecuteScript(g_GuildTowerNPC, '@RefineItem');
      end;
    $0BE0: begin
        m_sScriptParam[0] := IntToStr(MakeLong(ProcessMsg.nParam3, ProcessMsg.wParam));
        case ProcessMsg.nParam2 of
          1: ExecuteScript(g_ManageNPC, '@炼化内丹');
          2: ExecuteScript(g_ManageNPC, '@炼化元婴');
        end;
      end;
    $0BE1: begin
        ClientCreateSoul(0, LoByte(ProcessMsg.nParam2), HiByte(ProcessMsg.nParam2));
      end;
    $0BE2: begin
        ClientCreateSoul(1, ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    $0BE3: begin
        ExecuteScript(g_ManageNPC, '@元婴散魂');
      end;
    $0BE6: begin
        case ProcessMsg.wParam of
          0: ClientFelementOrderFlag(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
          1: begin                                                                                  //1
              m_sScriptParam[0] := '1';
              ExecuteScript(g_ManageNPC, '@离火封魔阵');
              SendDefMessage(SM_627, 0, 1037, 0, 0, '');
            end;
          10: begin                                                                                 //离开
              m_sScriptParam[0] := '0';                                                             //0
              ExecuteScript(g_ManageNPC, '@离火封魔阵');
            end;
          266: begin                                                                                //在来一次
              m_sScriptParam[0] := '2';                                                             //2
              ExecuteScript(g_ManageNPC, '@离火封魔阵');
            end;
        end;
      end;
    $0BE7: begin
        ClientReCallGuarder(ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3);
      end;
    CM_CTRLMENTAL: begin
        ClientCtrlMental(ProcessMsg.nParam2);                                                       //天元心法
      end;
    RM_3046: begin
        SendDefMessage(3046, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    CM_PHOENIXSEARCH: begin                                                                         //凤凰探宝
        ClientPhoenixSearch(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    RM_TIGERADDABIL: begin
        m_defMsg := MakeDefaultMsg(SM_TIGERABIL, 0, 0, 0, 0);
        SendSocket(@m_defMsg, EnCodeBuffer(@m_TorDDM.Tiger.AddAbil, SizeOf(TAddAbilityOfTiger) - 4));
      end;
    CM_TIGERTAKEON: begin
        case LoByte(ProcessMsg.nParam2) of
          0: ClientTakeOnInosculatePneumaItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          1: ClientTakeOffInosculatePneumaItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          2: ClientTakeOnTigerItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          3: ClientTakeOffTigerItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1);
          4: ClientTakeOnPetSoulItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1, ProcessMsg.nParam3);
          5: ClientTakeOffPetSoulItem(HiByte(ProcessMsg.nParam2), ProcessMsg.nParam1, ProcessMsg.nParam3);
        else
{$IF USESDK = DEBUG}
          MainOutMessage(Format('虎王消息:%d-%d-%d-%d-%d %s',
            [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        end;
      end;
    RM_HEARTFATEPOINT: begin
        m_defMsg := MakeDefaultMsg(SM_HEARTFATEPOINT, 0, 0, 0, 0);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_CTRLMENTAL: begin
        SendDefMessage(SM_CTRLMENTAL, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, 0, '');
      end;
    CM_GUILDCLAN: begin
        ClientQueryGuildClanList();
      end;
    CM_CLANOPERATE: begin
        ClientClanOperate(ProcessMsg.nParam2, ProcessMsg.sMsg);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('宗族消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    CM_CLANQUERY: begin
        ClientClanReQuery(ProcessMsg.nParam1, ProcessMsg.sMsg);
{$IF USESDK = DEBUG}
        MainOutMessage(Format('宗族消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
      end;
    RM_GETCATAPULT: begin
        m_defMsg := MakeDefaultMsg(SM_GETCATAPULT,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam);

        SendSocket(@m_defMsg, EnCodeBuffer(@ProcessMsg.nParam1, 4));
      end;
    RM_CATAPULTSTATUS: begin
        SendDefMessage(SM_CATAPULTSTATUS, Integer(ProcessMsg.BaseObject), 0, 0, ProcessMsg.wParam, '');
      end;
    SM_CATAPULTSTATUS: begin
{$IF USESDK = DEBUG}
        MainOutMessage(Format('投石车消息:%d-%d-%d-%d-%d %s',
          [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg]));
{$IFEND}
        if m_boCatapultMode then begin
          case ProcessMsg.wParam of
            0: begin                                                                                //移动
                m_boCatapultAttackMode := False;
                SendRefMsg(RM_CATAPULTSTATUS, 0, Integer(Self), 0, 0, '');
                SysMsg('投石车处于移动形态', c_Red, t_Hint);
              end;
            1: begin                                                                                //架起
                m_boCatapultAttackMode := True;
                SendRefMsg(RM_CATAPULTSTATUS, 1, Integer(Self), 0, 0, '');
                SysMsg('投石车处于架起形态', c_Red, t_Hint);
              end;
            2: begin                                                                                //弃车

              end;
          end;
        end;
      end;
    //      RM_CATAPULTATTACK: begin
    //        SendDefMessage(SM_CATAPULTATTACK, Integer(ProcessMsg.BaseObject), ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.wParam, '');
    //      end;
    SM_CATAPULTATTACK: begin
        ClientCatapultAttackTarget(ProcessMsg.wParam, ProcessMsg.nParam2, ProcessMsg.nParam3);
      end;
    CM_MAKEBABY: begin                                                                              //繁衍灵兽
        ClientPetMakeBaby(ProcessMsg.nParam1, MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3));
      end;
    CM_MAGBEAST: begin                                                                              //兽化
        ClientMagOfPetBeast(ProcessMsg.nParam1);
      end;
    RM_PETBEAST: begin
        m_defMsg := MakeDefaultMsg(SM_PETBEAST,
          Integer(ProcessMsg.BaseObject),
          LoWord(ProcessMsg.nParam1),
          HiWord(ProcessMsg.nParam1),
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_LAPIDATION: begin
        m_defMsg := MakeDefaultMsg(SM_LAPIDATION,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_USESPIRIT: begin                                                                             //使用神魂融合技能
     {   if (ProcessMsg.BaseObject = Self) and (m_MagicSkills[SKILL_SPIRITMERGE] <> nil) then begin
          DoSpell(m_MagicSkills[SKILL_SPIRITMERGE], m_nCurrX, m_nCurrY, nil);
        end;  }
      end;

    RM_SPIRITHP: begin                                                                              //神魂融合   神魂值
      {  if (ProcessMsg.BaseObject = Self) or (m_PneumaObject = ProcessMsg.BaseObject) then begin
          m_defMsg := MakeDefaultMsg(SM_SPIRITHP,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            0);
        end else begin
          m_defMsg := MakeDefaultMsg(SM_SPIRITHP,
            Integer(ProcessMsg.BaseObject),
            CalcCent(ProcessMsg.nParam1, ProcessMsg.nParam2),
            100,
            0);
        end;
        SendSocket(@m_defMsg, EnCodeBuffer(@ProcessMsg.wParam, 2));   }
      end;
    CM_CTRLDIVRATE: begin
        if not m_boPneuma and (m_PneumaObject <> nil) and (m_SpiritInfo.btLinkLv > 0) then begin
          m_SpiritInfo.btDivRate := _MIN((m_SpiritInfo.btLinkLv + 1) * 10, ProcessMsg.nParam2);
          SysMsg(Format('您的灵魂锁链当前可转移的的伤害比例为%d%%', [m_SpiritInfo.btDivRate]), c_Red, t_Hint);
        end;
      end;
    CM_COMPREHENDSKILL: begin
        m_sScriptParam[0] := IntToStr(ProcessMsg.nParam1);
        m_sScriptParam[1] := IntToStr(ProcessMsg.nParam2);
        if ProcessMsg.nParam3 = 0 then begin
          ExecuteScript(g_FunctionNPC, '@遗忘魂佑技能');
        end else begin
          ExecuteScript(g_FunctionNPC, '@领悟魂佑技能');
        end;
      end;
    CM_FREEPET: begin
        m_sScriptParam[0] := IntToStr(ProcessMsg.nParam1);
        ExecuteScript(g_FunctionNPC, '@放生灵兽');
      end;
    CM_ACHIEVEMENT: begin                                                                           //成就系统
        ClientAchievementSystem();
      end;
    CM_MAKEWENPEI: begin                                                                            //制做纹佩
        ClientMakeWenPei(LoByte(ProcessMsg.nParam2),                                                //主纹
          HiByte(ProcessMsg.nParam2),                                                               //精纹
          LoByte(ProcessMsg.nParam3),                                                               //底纹
          HiByte(ProcessMsg.nParam3)                                                                //边纹
          );
      end;
    CM_GETWENPEI_DEMAND: begin
        ClientGetWenPeiDemand(ProcessMsg.nParam1, ProcessMsg.nParam2);
      end;
    CM_TAKEWENPEI: begin                                                                            //强化 或 拆解 纹佩
        ClientTakeWenPei(MakeLong(ProcessMsg.nParam2, ProcessMsg.nParam3), ProcessMsg.nParam1);
      end;
    CM_COLLECTSUITS: begin                                                                          //成就之收集套装
        ClientCollectSuits(ProcessMsg.nParam3, ProcessMsg.nParam2, ProcessMsg.sMsg);
      end;
    CM_CHECKVALIDCODE: begin
        ClientCheckVerifyCode(ProcessMsg.sMsg);
      end;
    RM_DIRSHADOWHIT: begin
        m_defMsg := MakeDefaultMsg(SM_DIRSHADOWHIT,
          ProcessMsg.nParam1,
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_UPDATEITEM_MSG: begin
        m_defMsg := MakeDefaultMsg(ProcessMsg.wParam, Integer(ProcessMsg.BaseObject), ProcessMsg.nParam2, 0, ProcessMsg.nParam3);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
    RM_MAPEFFECT: begin
        SendDefMessage(SM_MAPEFFECT, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    RM_REFRESHRANK: begin                                                                           //刷新排行
        case ProcessMsg.nParam1 of
          0: g_RankManage.RefreshHeroRank(Self);
          1: g_RankManage.RefreshPneumaRank(Self);
          2: g_RankManage.RefreshOutPrenticeRank(Self);
          3: g_RankManage.RefreshPetRank(ProcessMsg.nParam2, Self);
          4: g_RankManage.RefreshGodPetRank(ProcessMsg.nParam2, Self);
          5: g_RankManage.RefreshMilitaryRank(Self);
          6: g_RankManage.RefreshRepressDemonRank(Self);
        end;
      end;
    RM_CHARSTATUSCHANGED_Delay: begin
        StatusChanged();
      end;
    RM_VEHICLEPOS: begin
        SendDefMessage(SM_VEHICLEPOS, ProcessMsg.wParam, ProcessMsg.nParam1, ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg);
      end;
    RM_REDPACKET: begin
        SendRedPacketWindow(ProcessMsg.wParam);
      end;
    RM_DEMONHIT: begin
        m_defMsg := MakeDefaultMsg(2454,
          Integer(ProcessMsg.BaseObject),
          ProcessMsg.nParam2,
          ProcessMsg.nParam3,
          ProcessMsg.wParam);
        SendSocket(@m_defMsg, ProcessMsg.sMsg);
      end;
   { 199:
    begin
      MainOutMessage(Format('精彩活动消息:%s-%d-%d-%d-%d-%d %s-%d',
          [m_sCharName, ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
          ProcessMsg.nParam2, ProcessMsg.nParam3, DeCodeString(ProcessMsg.sMsg), nObjCount]));
    end;    }
  else begin
      Result := inherited Operate(ProcessMsg);
    end;
{$IF CHECKNEWMSG =1}
    if not Result then
      MainOutMessage(Format('未处理的消息:%d-%d-%d-%d-%d %s %s  元神:%s',
        [ProcessMsg.wIdent, ProcessMsg.wParam, ProcessMsg.nParam1,
        ProcessMsg.nParam2, ProcessMsg.nParam3, ProcessMsg.sMsg, DeCodeString(ProcessMsg.sMsg), BoolToCStr(m_boPneuma)]));
{$IFEND}
  end;
end;

{将心魔属性添加到装备}

procedure TPlayObject.AddEvilToItemB(nWhere: word; nMakeIndex, BottleIndex:
  Integer);
var
  UserItem, BottleItem                  : pTUserItem;
  s                                     : string;
  pStdItem                              : pTStdItem;
begin
  GetUserItemByMakeIndex(BottleIndex, BottleItem);
  GetUserItemByMakeIndex(nMakeIndex, UserItem);
  if (UserItem <> nil) and (BottleItem <> nil) then begin
    if (BottleItem.Evil.sName = '') or (BottleItem.Evil.MakeIndex = 0) then begin
      SysMsg('无法从玉净瓶中感应到心魔气息,不能附魔!', c_Red, t_Hint);
      Exit;
    end;
    if BottleItem.Evil.wPower < 2000 then begin
      SysMsg('玉净瓶的镇魔力量太弱,不能附魔!', c_Red, t_Hint);
      Exit;
    end;
    UserItem.Evil := BottleItem.Evil;
    UserItem.Evil.MakeIndex := UserItem.MakeIndex;
    {获取心魔随机属性}
    ItemUnit.RandomItemEvil(UserItem);                                                              //获取附魔属性
    SendUpdateItem(UserItem, False);

    FillChar(BottleItem.Evil, SizeOf(TEvil), #0);                                                   //删除玉净瓶心魔数据
    SendUpdateItem(BottleItem, False);
    SendDefMessage(SM_ITEMEVIL, Integer(Self), LoWord(BottleIndex), HiWord(BottleIndex), 0, '');
    SendRefMsg(RM_510, 1, 0, 63, 0, '');
    pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (pStdItem <> nil) then
      SysMsg(Format('心魔的魔力精髓,已经附注到你的%s,你的%s获得了强大的威力!', [pStdItem^.FilterName, pStdItem^.FilterName]), c_Red, t_Hint);
  end;
end;

{棋座留言}

procedure TPlayObject.AddFlagComment(nflagType: Integer; NPCID: Integer;
  nMsgLen: Integer; sMsg: string);
var
  s                                     : string;
  NPC                                   : TNormNpc;
begin
  NPC := UserEngine.FindMerchant(TObject(NPCID));
  if NPC = nil then NPC := UserEngine.FindNPC(TObject(NPCID));
  if NPC = nil then Exit;
  if CheckFilterWords(sMsg) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '输入内容含有非法字符!');
    Exit;
  end;
  NPC.AddComment(Self, DeCodeString(sMsg));
end;

procedure TPlayObject.AddToFriendList(FriendName: string);
var
  i                                     : Integer;
  boFound                               : Boolean;
begin
  boFound := False;
  for i := 0 to m_FriendsList.Count - 1 do
    if m_FriendsList[i] = FriendName then begin
      boFound := True;
      Break;
    end;
  if not boFound then begin
    m_FriendsList.Add(FriendName);
    SendDefMessage(SM_AddFriend, 0, 0, 0, 0, FriendName);
  end;
end;

procedure TPlayObject.BaseObjectMove(sMAP, sX, sY: string);                                         //004BD0C4
var
  Envir                                 : TEnvirnoment;
  nX, nY                                : Integer;
begin
  Envir := m_PEnvir;
  if sMAP = '' then sMAP := m_sMapName;
  if (sX <> '') and (sY <> '') then begin
    nX := Str_ToInt(sX, 0);
    nY := Str_ToInt(sY, 0);
    SpaceMove(sMAP, nX, nY, 0, nil);
  end else begin
    MapRandomMove(sMAP, 0, nil);
  end;
  if (Envir <> m_PEnvir) and (m_btRaceServer = RC_PLAYOBJECT) then begin
    m_boTimeRecall := False;
  end;

end;

procedure TPlayObject.CancelDoShop;
var
  DoShopResult                          : TDoShopResult;
begin
  //如果当前在摆摊,则强制收摊
  if m_wShopItemCount > 0 then begin
    m_wShopItemCount := 0;
    DoShopResult.ShopType := 0;
    DoShopResult.RetCode := $FF;
    DoShopResult.FlagType := 0;
    DoShopResult.FlagColor := 0;
    m_defMsg := MakeDefaultMsg(SM_DOSHOP, Integer(Self), m_nCurrX, m_nCurrY, m_btDirection);
    SendSocket(@m_defMsg, EnCodeBuffer(@DoShopResult, SizeOf(TDoShopResult)));
    SendRefMsg(RM_DOSHOP, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), $FF, 0, '');
  end;
end;

function TPlayObject.CancelGroup: Boolean;
resourcestring
  sCanceGrop                            = '你的小组被解散了...';
begin
  Result := True;
  if m_GroupMembers.Count <= 1 then begin
    SendGroupText(sCanceGrop);
    m_GroupMembers.Clear;
    m_GroupOwner := nil;
    Result := False;
  end;
end;

procedure TPlayObject.ChangeMasterName(sHumanName, sMasterName: string;
  boMaster: Boolean);
var
  PlayObject, Hum                       : TPlayObject;
begin
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    if CompareText(sMasterName, '无') = 0 then begin
      if boMaster then begin
        PlayObject.m_sMasterName[1] := '';
        PlayObject.m_sMasterName[2] := '';
        PlayObject.m_sMasterName[3] := '';
      end else begin
        PlayObject.m_sMasterName[1] := '';
      end;
      PlayObject.m_boMaster := False;
    end else begin
      if boMaster then begin
        PlayObject.m_boMaster := True;
        if (PlayObject.m_sMasterName[1] = '') then
          PlayObject.m_sMasterName[1] := sMasterName
        else if (PlayObject.m_sMasterName[2] = '') then
          PlayObject.m_sMasterName[2] := sMasterName
        else if (PlayObject.m_sMasterName[3] = '') then
          PlayObject.m_sMasterName[3] := sMasterName;
      end else begin
        PlayObject.m_sMasterName[1] := sMasterName;
        PlayObject.m_boMaster := False;
        PlayObject.SysMsg('拜师成功', c_Red, t_Hint);
      end;
    end;
    PlayObject.RefShowName;
    PlayObject.SendFiendList(1);
    Hum := UserEngine.GetPlayObject(sMasterName);
    if Hum <> nil then begin
      Hum.SendFiendList(2);
      Hum.SendMeOnlineState(1, 1);
      Hum.RefShowName;
    end;

    //    PlayObject.SendMeOnlineState(1, 2);
  end;
end;

procedure TPlayObject.ChangePneumaState;
var
  i, nSlave                             : Integer;
  Slave                                 : TBaseObject;
resourcestring
  sHint1                                = '魂魄力量暂时无法聚拢,你的元神分身不能幻化。';
  sHint2                                = '魂魄力量聚拢,你的元神分身幻化成了元神灵珠。';
  sHint3                                = '神奇的力量凝聚,你的元神分身被唤醒了。';
begin
  if m_boPneuma then Exit;
  if (m_PneumaObject = nil) or m_PneumaObject.m_boGhost or m_PneumaObject.m_boDeath then Exit;

  //  if TPlayObject(m_PneumaObject).m_boRideOn then Exit;

  if not TPlayObject(m_PneumaObject).m_boPneumaEffMode then begin
    if g_Config.boNoElfBead then Exit;                                                              //不允许灵珠模式,则直接返回
    if GetTickCount - TPlayObject(m_PneumaObject).m_dwPneumaChangeTick < 9 * 1000 then Exit;        //防止客户端错误引起的刷屏
    if GetTickCount - TPlayObject(m_PneumaObject).m_dwPneumaChangeTick < 10 * 1000 then begin       //从人形转换为灵珠需要时间间隔
      SysMsg(sHint1, c_Red, t_Hint);
      Exit;
    end;
    SysMsg(sHint2, c_Red, t_Hint);
    TPlayObject(m_PneumaObject).m_boPneumaEffMode := True;
    m_PneumaObject.SendRefMsg(RM_YSSTATECHANGED, 1, Integer(m_PneumaObject), 0, 0, '');
    TPlayObject(m_PneumaObject).m_dwPneumaChangeTick := GetTickCount;

    //清除宝宝
    for i := 0 to m_PneumaObject.m_SlaveList.Count - 1 do begin
      Slave := TBaseObject(m_PneumaObject.m_SlaveList.Items[i]);
      nSlave := Integer(Slave);
      TPlayObject(m_PneumaObject).SendDefMessage(SM_SLAVEINFO, Integer(m_PneumaObject), 0, 0, 1, EnCodeBuffer(@nSlave, SizeOf(Integer)));
      Slave.MakeGhost();
    end;
    m_PneumaObject.m_SlaveList.Clear;
  end else begin
    TPlayObject(m_PneumaObject).m_dwPneumaChangeTick := GetTickCount;
    SysMsg(sHint3, c_Red, t_Hint);
    TPlayObject(m_PneumaObject).m_boPneumaEffMode := False;
    m_PneumaObject.SendRefMsg(RM_YSSTATECHANGED, 0, Integer(m_PneumaObject), 0, 0, '');
  end;
end;

procedure TPlayObject.ChangeServerMakeSlave(SalveInfo: pTSlaveInfo);                                //004DF84C
var
  nSlaveCount                           : Integer;
  BaseObject                            : TBaseObject;
begin
  if m_btJob = 2 then begin                                                                         //道士只允许招一个宝宝
    nSlaveCount := 1;
  end else begin                                                                                    //其他职业允许招5个
    nSlaveCount := 5;
  end;
  BaseObject := MakeSlave(SalveInfo.sSalveName, 3, SalveInfo.btSalveLevel, nSlaveCount, SalveInfo.dwRoyaltySec, -1);
  if BaseObject <> nil then begin
    BaseObject.m_nSlaveKillMonCount := SalveInfo.nKillCount;
    BaseObject.m_wSlaveExpLevel := SalveInfo.btSlaveExpLevel;
    BaseObject.m_WAbil.dwHP := SalveInfo.nHP;
    BaseObject.m_WAbil.dwMP := SalveInfo.nMP;
    if (1500 - SalveInfo.btSalveLevel * 200) < BaseObject.m_nWalkSpeed then begin
      BaseObject.m_nWalkSpeed := 1500 - SalveInfo.btSalveLevel * 200;
    end;
    if (2000 - SalveInfo.btSalveLevel * 200) < BaseObject.m_nNextHitTime then begin
      BaseObject.m_nNextHitTime := 2000 - SalveInfo.btSalveLevel * 200;
    end;
    RecalcAbilitys();
  end;
end;

function TPlayObject.CheckActionStatus(wIdent: word; var dwDelayTime: LongWord):
  Boolean;
var
  dwCheckTime                           : LongWord;
  //dwCurrTick:LongWord;
  dwActionIntervalTime                  : LongWord;
begin
  Result := False;
  dwDelayTime := 0;
  //检查人物弯腰停留时间
  if not g_Config.boDisableStruck then begin
    dwCheckTime := GetTickCount - m_dwStruckTick;
    if g_Config.dwStruckTime > dwCheckTime then begin
      dwDelayTime := g_Config.dwStruckTime - dwCheckTime;
      m_btOldDir := m_btDirection;
      Exit;
    end;
  end;

  //检查二个不同操作之间所需间隔时间
  dwCheckTime := GetTickCount - m_dwActionTick;

  if m_boTestSpeedMode then begin
    SysMsg('间隔: ' + IntToStr(dwCheckTime), c_Blue, t_Notice);
  end;

  if m_wOldIdent = wIdent then begin                                                                //当二次操作一样时,则将 boFirst 设置为 真 ,退出由调用函数本身检查二个相同操作之间的间隔时间
    Result := True;
    Exit;
  end;
  if not g_Config.boControlActionInterval then begin
    Result := True;
    Exit;
  end;

  dwActionIntervalTime := m_dwActionIntervalTime;
  case wIdent of
    CM_LONGHIT: begin
        //跑位刺杀
        if g_Config.boControlRunLongHit and (m_wOldIdent = CM_RUN) and
          (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunLongHitIntervalTime;
        end;
      end;
    CM_HIT: begin
        //走位攻击
        if g_Config.boControlWalkHit and (m_wOldIdent = CM_WALK) and (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwWalkHitIntervalTime;
        end;
        //跑位攻击
        if g_Config.boControlRunHit and (m_wOldIdent = CM_RUN) and (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunHitIntervalTime;
        end;
      end;
    CM_RUN: begin
        //跑位刺杀
        if g_Config.boControlRunLongHit and (m_wOldIdent = CM_LONGHIT) and
          (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunLongHitIntervalTime;
        end;
        //跑位攻击
        if g_Config.boControlRunHit and (m_wOldIdent = CM_HIT) and (m_btOldDir
          <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunHitIntervalTime;
        end;
        //跑位魔法
        if g_Config.boControlRunMagic and (m_wOldIdent = CM_SPELL) and
          (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunMagicIntervalTime;
        end;
      end;
    CM_WALK: begin
        //走位攻击
        if g_Config.boControlWalkHit and (m_wOldIdent = CM_HIT) and (m_btOldDir
          <> m_btDirection) then begin
          dwActionIntervalTime := m_dwWalkHitIntervalTime;
        end;
        //跑位刺杀
        if g_Config.boControlRunLongHit and (m_wOldIdent = CM_LONGHIT) and
          (m_btOldDir <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunLongHitIntervalTime;
        end;
      end;
    CM_SPELL: begin
        //跑位魔法
        if g_Config.boControlRunMagic and (m_wOldIdent = CM_RUN) and (m_btOldDir
          <> m_btDirection) then begin
          dwActionIntervalTime := m_dwRunMagicIntervalTime;
        end;
      end;
  end;

  //将几个攻击操作合并成一个攻击操作代码
  if (wIdent = CM_HIT) or
    (wIdent = CM_HEAVYHIT) or
    (wIdent = CM_BIGHIT) or
    (wIdent = CM_POWERHIT) or
    //     (wIdent = CM_LONGHIT) or
  (wIdent = CM_WIDEHIT) or
    (wIdent = CM_FIREHIT) or
    (wIdent = CM_3026) then begin

    wIdent := CM_HIT;
  end;

  if dwCheckTime >= dwActionIntervalTime then begin
    m_dwActionTick := GetTickCount();
    Result := True;
  end else begin
    dwDelayTime := dwActionIntervalTime - dwCheckTime;
  end;
  m_wOldIdent := wIdent;
  m_btOldDir := m_btDirection;
end;

function TPlayObject.CheckDenyLogon(): Boolean;
begin
  Result := False;
  if GetDenyIPaddrList(m_sIPaddr) then begin
    SysMsg(g_sYourIPaddrDenyLogon, c_Red, t_Hint);
    Result := True;
  end else
    if GetDenyAccountList(m_sUserID) then begin
      SysMsg(g_sYourAccountDenyLogon, c_Red, t_Hint);
      Result := True;
    end else
      if GetDenyChrNameList(m_sCharName) then begin
        SysMsg(g_sYourCharNameDenyLogon, c_Red, t_Hint);
        Result := True;
      end;
  if Result then m_boEmergencyClose := True;
end;

//检查物品和帐户之间的绑定关系

function TPlayObject.CheckItemBindUse(UserItem: pTUserItem): Boolean;
var
  i                                     : Integer;
  ItemBind                              : pTItemBind;
begin
  Result := True;
  //检查物品和帐号的绑定
  for i := 0 to g_ItemBindAccount.Count - 1 do begin
    ItemBind := g_ItemBindAccount.Items[i];
    if (ItemBind.nMakeIdex = UserItem.MakeIndex) and
      (ItemBind.nItemIdx = UserItem.wIndex) then begin
      Result := False;
      if (CompareText(ItemBind.sBindName, m_sUserID) = 0) then begin
        Result := True;
      end else begin
        SysMsg(g_sItemIsNotThisAccount, c_Red, t_Hint);
        //此物品不为此帐号所有!!!
      end;
      Exit;
    end;
  end;

  //检查物品和IP的绑定
  for i := 0 to g_ItemBindIPaddr.Count - 1 do begin
    ItemBind := g_ItemBindIPaddr.Items[i];
    if (ItemBind.nMakeIdex = UserItem.MakeIndex) and
      (ItemBind.nItemIdx = UserItem.wIndex) then begin
      Result := False;
      if (CompareText(ItemBind.sBindName, m_sIPaddr) = 0) then begin
        Result := True;
      end else begin
        SysMsg(g_sItemIsNotThisIPaddr, c_Red, t_Hint);
        //此物品不为此IP所有!!!
      end;
      Exit;
    end;
  end;

  //检查物品和人物的绑定
  for i := 0 to g_ItemBindCharName.Count - 1 do begin
    ItemBind := g_ItemBindCharName.Items[i];
    if (ItemBind.nMakeIdex = UserItem.MakeIndex) and
      (ItemBind.nItemIdx = UserItem.wIndex) then begin
      Result := False;
      if (CompareText(ItemBind.sBindName, m_sCharName) = 0) then begin
        Result := True;
      end else begin
        SysMsg(g_sItemIsNotThisCharName, c_Red, t_Hint);
        //此物品不为你所有!!!
      end;
      Exit;
    end;
  end;
  if Result then begin
    Result := False;
    if m_Abil.level >= UserItem.btItemExt[11] then begin
      Result := True;
    end else begin
      SysMsg(g_sLevelNot, c_Red, t_Hint);
    end;
  end;
end;

function TPlayObject.CheckItemsNeed(StdItem: pTStdItem): Boolean;
var
  Castle                                : TUserCastle;
begin
  Result := True;
  Castle := g_CastleManager.IsCastleMember(Self);
  case StdItem.Need of
    6: begin                                                                                        //行会需要的物品
        if (m_MyGuild = nil) then begin
          Result := False;
        end;
      end;
    60: begin                                                                                       //掌门人的物品
        if (m_MyGuild = nil) or (m_nGuildRankNo <> 1) then begin
          Result := False;
        end;
      end;
    71: begin                                                                                       //城堡物品
        if Castle = nil then begin
          Result := False;
        end;
      end;
    70: begin                                                                                       //城主物品
        if (Castle = nil) or (m_nGuildRankNo <> 1) then begin
          Result := False;
        end;
      end;
    8: begin                                                                                        //会员物品
        if m_nMemberType = 0 then Result := False;
      end;
    81: begin                                                                                       //
        if (m_nMemberType <> LoWord(StdItem.NeedLevel)) or (m_nMemberLevel <
          HiWord(StdItem.NeedLevel)) then
          Result := False;
      end;
    82: begin
        if (m_nMemberType < LoWord(StdItem.NeedLevel)) or (m_nMemberLevel <
          HiWord(StdItem.NeedLevel)) then
          Result := False;
      end;
  end;
end;

procedure TPlayObject.CheckMarry;
var
  boIsfound                             : Boolean;
  sUnMarryFileName                      : string;
  LoadList                              : TStringList;
  i                                     : Integer;
  sSayMsg                               : string;
begin
  boIsfound := False;
  sUnMarryFileName := g_Config.sEnvirDir + 'UnMarry.txt';
  if FileExists(sUnMarryFileName) then begin
    LoadList := TStringList.Create;
    LoadList.LoadFromFile(sUnMarryFileName);
    for i := LoadList.Count - 1 downto 0 do begin
      if CompareText(LoadList.Strings[i], m_sCharName) = 0 then begin
        LoadList.Delete(i);
        boIsfound := True;
        Break;
      end;
    end;
    LoadList.SaveToFile(sUnMarryFileName);
    LoadList.free;
  end;
  if boIsfound then begin
    if m_btGender = 0 then begin
      sSayMsg := AnsiReplaceText(g_sfUnMarryManLoginMsg, '%d', m_sDearName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sDearName);
    end else begin
      sSayMsg := AnsiReplaceText(g_sfUnMarryWoManLoginMsg, '%d', m_sCharName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
    end;
    if g_Config.boShowScriptActionMsg then SysMsg(sSayMsg, c_Red, t_Hint);
    m_sDearName := '';
    RefShowName;
  end;
  m_DearHuman := UserEngine.GetPlayObject(m_sDearName);
  if m_DearHuman <> nil then begin
    m_DearHuman.m_DearHuman := Self;
    if m_btGender = 0 then begin
      sSayMsg := AnsiReplaceText(g_sManLoginDearOnlineSelfMsg, '%d',
        m_sDearName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_DearHuman.m_PEnvir.m_sMapDesc);
      sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_DearHuman.m_nCurrX));
      sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_DearHuman.m_nCurrY));
      if g_Config.boShowScriptActionMsg then SysMsg(sSayMsg, c_Blue, t_Hint);

      sSayMsg := AnsiReplaceText(g_sManLoginDearOnlineDearMsg, '%d',
        m_sDearName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
      sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
      sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
      if g_Config.boShowScriptActionMsg then
        m_DearHuman.SysMsg(sSayMsg, c_Blue, t_Hint);
    end else begin
      sSayMsg := AnsiReplaceText(g_sWoManLoginDearOnlineSelfMsg, '%d',
        m_sDearName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_DearHuman.m_PEnvir.m_sMapDesc);
      sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_DearHuman.m_nCurrX));
      sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_DearHuman.m_nCurrY));
      if g_Config.boShowScriptActionMsg then SysMsg(sSayMsg, c_Blue, t_Hint);

      sSayMsg := AnsiReplaceText(g_sWoManLoginDearOnlineDearMsg, '%d',
        m_sDearName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
      sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
      sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
      if g_Config.boShowScriptActionMsg then
        m_DearHuman.SysMsg(sSayMsg, c_Blue, t_Hint);
    end;
  end else begin
    if m_btGender = 0 then begin
      if g_Config.boOldClientShowHiLevel then
        SysMsg(g_sManLoginDearNotOnlineMsg, c_Red, t_Hint);
    end else begin
      if g_Config.boOldClientShowHiLevel then
        SysMsg(g_sWoManLoginDearNotOnlineMsg, c_Red, t_Hint);
    end;
  end;
end;

procedure TPlayObject.CheckMaster;
var
  boIsfound                             : Boolean;
  sSayMsg, sHumName                     : string;
  i                                     : Integer;
  human                                 : TPlayObject;
begin
  {处理强行脱离师徒关系}
  boIsfound := False;
  sHumName := '';
  if not m_boMaster then begin                                                                      //徒弟上线
    g_UnForceMasterList.Lock;
    try
      for i := g_UnForceMasterList.Count - 1 downto 0 do begin
        if CompareText(g_UnForceMasterList.Strings[i], m_sCharName) = 0 then begin
          g_UnForceMasterList.Delete(i);
          SaveUnForceMasterList();
          boIsfound := True;
          Break;
        end;
      end;
    finally
      g_UnForceMasterList.UnLock;
    end;
    if boIsfound then begin
      sSayMsg := AnsiReplaceText(g_sfUnMasterListLoginMsg, '%d', m_sMasterName[1]);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sMasterName[1]);
      m_sMasterName[1] := '';
      RefShowName;
      if g_Config.boOldClientShowHiLevel then SysMsg(sSayMsg, c_Blue, t_Hint);
    end;
  end else begin                                                                                    //师傅上线
    g_UnForceMasterList.Lock;
    try
      for i := g_UnForceMasterList.Count - 1 downto 0 do begin
        sHumName := g_UnForceMasterList.Strings[i];
        if (CompareText(sHumName, m_sMasterName[1]) = 0) or
          (CompareText(sHumName, m_sMasterName[2]) = 0) or
          (CompareText(sHumName, m_sMasterName[3]) = 0) then begin

          g_UnForceMasterList.Delete(i);
          SaveUnForceMasterList();
          boIsfound := True;
          Break;
        end;
      end;
    finally
      g_UnForceMasterList.UnLock;
    end;

    if boIsfound then begin
      sSayMsg := AnsiReplaceText(g_sfUnMasterLoginMsg, '%d', sHumName);
      sSayMsg := AnsiReplaceText(sSayMsg, '%s', sHumName);
      if m_sMasterName[1] = sHumName then m_sMasterName[1] := ''
      else if m_sMasterName[2] = sHumName then m_sMasterName[2] := ''
      else if m_sMasterName[3] = sHumName then m_sMasterName[3] := '';
      RefShowName;
      if g_Config.boOldClientShowHiLevel then SysMsg(sSayMsg, c_Blue, t_Hint);
    end;
  end;

  {处理徒弟出师}
  if (m_sMasterName[1] <> '') and not m_boMaster then begin                                         //徒弟
    if m_Abil.level >= g_Config.nMasterOKLevel then begin                                           //出师等级
      human := UserEngine.GetPlayObject(m_sMasterName[1]);
      {师傅在线}
      if (human <> nil) and (not human.m_boDeath) and (not human.m_boGhost) then begin
        sSayMsg := AnsiReplaceText(g_sYourMasterListUnMasterOKMsg, '%d', m_sCharName);

        if g_Config.boOldClientShowHiLevel then
          human.SysMsg(sSayMsg, c_Red, t_Hint);

        if g_Config.boOldClientShowHiLevel then
          SysMsg(g_sYouAreUnMasterOKMsg, c_Red, t_Hint);

        human.ExecuteScript(g_ManageNPC, '@徒弟出师');

        {从师傅的徒弟名单中删除}
        for i := human.m_MasterList.Count - 1 downto 0 do begin
          if human.m_MasterList.Items[i] = Self then begin
            human.m_MasterList.Delete(i);
            Break;
          end;
        end;
        {将徒弟从师傅的名字上去掉}
        if m_sCharName = human.m_sMasterName[1] then
          human.m_sMasterName[1] := ''
        else if m_sCharName = human.m_sMasterName[2] then
          human.m_sMasterName[2] := ''
        else if m_sCharName = human.m_sMasterName[3] then
          human.m_sMasterName[3] := '';
        human.RefShowName;
        m_sMasterName[1] := '';
        RefShowName;
        {师傅加声望}
        if human.m_wCreditPoint + g_Config.nMasterOKCreditPoint <= High(word) then begin
          Inc(human.m_wCreditPoint, g_Config.nMasterOKCreditPoint);
          human.SendUpdateMsg(human, RM_SUBABILITY, 0, 0, 0, 0, '');
        end;
        Inc(human.m_nBonusPoint, g_Config.nMasterOKBonusPoint);
        Inc(human.m_wPrenticeCount);                                                                //出师数量加 1
        human.SendMsg(human, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
        //刷新出师排行
        g_RankManage.RefreshOutPrenticeRank(human);
      end else begin
        {如果师傅不在线,则保存到记录中}
        g_UnMasterList.Lock;
        try
          boIsfound := False;
          for i := 0 to g_UnMasterList.Count - 1 do begin
            if CompareText(g_UnMasterList.Strings[i], m_sCharName) = 0 then begin
              boIsfound := True;
              Break;
            end;
          end;
          if not boIsfound then begin
            g_UnMasterList.Add(m_sCharName);
          end;
        finally
          g_UnMasterList.UnLock;
        end;
        if not boIsfound then begin
          SaveUnMasterList();
        end;
        if g_Config.boOldClientShowHiLevel then
          SysMsg(g_sYouAreUnMasterOKMsg, c_Red, t_Hint);
        m_sMasterName[1] := '';
        RefShowName;
      end;

      //徒弟出师加声望
      if g_Config.boPrenticeAddCredit and (m_wCreditPoint + g_Config.nPrenticeCreditPoint <= High(word)) then begin
        Inc(m_wCreditPoint, g_Config.nPrenticeCreditPoint);
        SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
        Inc(m_nBonusPoint, g_Config.nPrenticeBonusPoint);
        SendMsg(Self, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
      end;
      //触发Qmanage.txt中的脚本
      ExecuteScript(g_ManageNPC, '@本人出师');
    end;
  end;

  if (not m_boMaster) and (m_sMasterName[1] = '') then Exit;

  //处理出师记录
  boIsfound := False;
  sHumName := '';
  g_UnMasterList.Lock;
  try
    for i := g_UnMasterList.Count - 1 downto 0 do begin
      if (CompareText(g_UnMasterList.Strings[i], m_sMasterName[1]) = 0) or
        (CompareText(g_UnMasterList.Strings[i], m_sMasterName[2]) = 0) or
        (CompareText(g_UnMasterList.Strings[i], m_sMasterName[3]) = 0) then begin
        sHumName := g_UnMasterList.Strings[i];
        g_UnMasterList.Delete(i);                                                                   //从出师名单中删除
        SaveUnMasterList();
        boIsfound := True;
        Break;
      end;
    end;
  finally
    g_UnMasterList.UnLock;
  end;

  if boIsfound and m_boMaster then begin
    SysMsg(g_sUnMasterLoginMsg, c_Red, t_Hint);                                                     //你的一个徒弟已经圆满出师了!!!
    if sHumName = m_sMasterName[1] then m_sMasterName[1] := ''
    else if sHumName = m_sMasterName[2] then m_sMasterName[2] := ''
    else if sHumName = m_sMasterName[3] then m_sMasterName[3] := '';
    RefShowName;
    if m_wCreditPoint + g_Config.nMasterOKCreditPoint <= High(word) then begin
      Inc(m_wCreditPoint, g_Config.nMasterOKCreditPoint);
      SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
    end;
    Inc(m_nBonusPoint, g_Config.nMasterOKBonusPoint);
    Inc(m_wPrenticeCount);                                                                          //出师数量加 1
    //刷新出师排行
    g_RankManage.RefreshOutPrenticeRank(Self);
    SendMsg(Self, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
    ExecuteScript(g_ManageNPC, '@徒弟出师');
  end;

  if m_boMaster and (m_sMasterName[1] = '') and (m_sMasterName[2] = '') and (m_sMasterName[3] = '') then begin
    m_boMaster := False;
    Exit;
  end;
  {
     if m_boMaster then begin
       //师父上线通知
       m_MasterHuman := UserEngine.GetPlayObject(m_sMasterName[1]);
       if m_MasterHuman <> nil then begin
         m_MasterHuman.m_MasterHuman := Self;
         m_MasterList.Add(m_MasterHuman);

         sSayMsg := AnsiReplaceText(g_sMasterOnlineSelfMsg, '%d',
           m_sMasterName[1]);
         sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
         sSayMsg := AnsiReplaceText(sSayMsg, '%m',
           m_MasterHuman.m_PEnvir.m_sMapDesc);
         sSayMsg := AnsiReplaceText(sSayMsg, '%x',
           IntToStr(m_MasterHuman.m_nCurrX));
         sSayMsg := AnsiReplaceText(sSayMsg, '%y',
           IntToStr(m_MasterHuman.m_nCurrY));
         if g_Config.boOldClientShowHiLevel then SysMsg(sSayMsg, c_Blue, t_Hint);

         sSayMsg := AnsiReplaceText(g_sMasterOnlineMasterListMsg, '%d',
           m_sMasterName[1]);
         sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
         sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
         sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
         sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
         if g_Config.boOldClientShowHiLevel then
           m_MasterHuman.SysMsg(sSayMsg, c_Blue, t_Hint);
       end else begin
         if g_Config.boOldClientShowHiLevel then
           SysMsg(g_sMasterNotOnlineMsg, c_Red, t_Hint);
       end;
     end else begin
       //徒弟上线通知
       if m_sMasterName[1] <> '' then begin
         m_MasterHuman := UserEngine.GetPlayObject(m_sMasterName[1]);
         if m_MasterHuman <> nil then begin

           if m_MasterHuman.m_sMasterName[1] = m_sCharName then begin
             m_MasterHuman.m_MasterHuman := Self;
           end;

           m_MasterHuman.m_MasterList.Add(Self);

           sSayMsg := AnsiReplaceText(g_sMasterListOnlineSelfMsg, '%d',
             m_sMasterName[1]);
           sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
           sSayMsg := AnsiReplaceText(sSayMsg, '%m',
             m_MasterHuman.m_PEnvir.m_sMapDesc);
           sSayMsg := AnsiReplaceText(sSayMsg, '%x',
             IntToStr(m_MasterHuman.m_nCurrX));
           sSayMsg := AnsiReplaceText(sSayMsg, '%y',
             IntToStr(m_MasterHuman.m_nCurrY));
           if g_Config.boOldClientShowHiLevel then
             SysMsg(sSayMsg, c_Blue, t_Hint);

           sSayMsg := AnsiReplaceText(g_sMasterListOnlineMasterMsg, '%d',
             m_sMasterName[1]);
           sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
           sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
           sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
           sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
           if g_Config.boOldClientShowHiLevel then
             m_MasterHuman.SysMsg(sSayMsg, c_Blue, t_Hint);
         end else begin
           if g_Config.boOldClientShowHiLevel then
             SysMsg(g_sMasterListNotOnlineMsg, c_Red, t_Hint);
         end;
       end;
     end;
     }
end;

procedure TPlayObject.CheckPackPetShop();
var
  i                                     : Integer;
  nCode                                 : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  tm                                    : LongWord;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::CheckPackPetShop Name=%s Code=%d';
begin
  try
    nCode := 0;
    if m_PetInfo[1].nMakeIndex <> 0 then begin
      m_PackPet := g_PetBoothManage.GetPetSellObject(m_dwDBIndex);
      nCode := 1;
      if (m_PackPet <> nil) and (not m_PackPet.m_boGhost) and (not m_PackPet.m_boDeath) then begin
        if (m_PetInfo[0].nMakeIndex = m_PetInfo[1].nMakeIndex) or
          (m_PetInfo[2].nMakeIndex = m_PetInfo[1].nMakeIndex) or
          (m_PetInfo[3].nMakeIndex = m_PetInfo[1].nMakeIndex) or
          (m_PetInfo[4].nMakeIndex = m_PetInfo[1].nMakeIndex) or
          (m_PetInfo[5].nMakeIndex = m_PetInfo[1].nMakeIndex) then begin
          PetHide(m_PetInfo[1].nMakeIndex);
        end;

        m_nPetTargetX := m_PackPet.m_nCurrX;
        m_nPetTargetY := m_PackPet.m_nCurrY;
        nCode := 2;
        SendDefMessage(34979, 0, 1, 0, 0, Format('你的宠物在%s(%d:%d)为你守摊。',
          [m_PackPet.m_PEnvir.m_sMapDesc, m_PackPet.m_nCurrX, m_PackPet.m_nCurrY]));
        SysMsg(Format('你的宠物在%s(%d:%d)为你守摊。',
          [m_PackPet.m_PEnvir.m_sMapDesc, m_PackPet.m_nCurrX, m_PackPet.m_nCurrY]), c_Red, t_Hint);
        nCode := 3;
        if GetUserItemByMakeIndex(m_PetInfo[1].nMakeIndex, UserItem) >= 0 then begin
          nCode := 4;
          m_PetInfo[1].wLevel := MakeWord(UserItem.btValue[4], UserItem.btValue[5]);
          m_PetInfo[1].btType := 0;
          m_PetInfo[1].btReLive := UserItem.btValue[9];
          m_PetInfo[1].btRideFightSpeed := UserItem.btRideSpeed;
          m_PetInfo[1].btAttack := UserItem.btExtra.btAttack;                                       //骑战技能攻击距离
          //骑战速度
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          nCode := 5;
          if (StdItem <> nil) then begin
            if (UserItem.btValue[9] > 0) then begin
              nCode := 6;
              case StdItem.AniCount of
                0: m_PetInfo[1].btType := 10 + UserItem.btValue[8];
                1: m_PetInfo[1].btType := 13 + UserItem.btValue[8];
                2: m_PetInfo[1].btType := 16 + UserItem.btValue[8];
                3: m_PetInfo[1].btType := 19 + UserItem.btValue[8];
                4: m_PetInfo[1].btType := 22 + UserItem.btValue[8];
                5: m_PetInfo[1].btType := 25 + UserItem.btValue[8];
                6: m_PetInfo[1].btType := 28 + UserItem.btValue[8];
                7: m_PetInfo[1].btType := 31 + UserItem.btValue[8];
                8: m_PetInfo[1].btType := 34 + UserItem.btValue[8];
                9: m_PetInfo[1].btType := 37 + UserItem.btValue[8];
                10: m_PetInfo[1].btType := 38 + UserItem.btValue[8];
                11: m_PetInfo[1].btType := 43 + UserItem.btValue[8];
                12: m_PetInfo[1].btType := 44 + UserItem.btValue[8];
                13: m_PetInfo[1].btType := 45 + UserItem.btValue[8];
                14: m_PetInfo[1].btType := 40 + UserItem.btValue[8];
                15: m_PetInfo[1].btType := 46 + UserItem.btValue[8];
              end;
            end else begin
              nCode := 7;
              case StdItem.AniCount of
                0: m_PetInfo[1].btType := 11;
                1: m_PetInfo[1].btType := 14;
                2: m_PetInfo[1].btType := 17;
                3: m_PetInfo[1].btType := 20;
                4: m_PetInfo[1].btType := 23;
                5: m_PetInfo[1].btType := 26;
                6: m_PetInfo[1].btType := 29;
                7: m_PetInfo[1].btType := 32;
                8: m_PetInfo[1].btType := 35;
                9: m_PetInfo[1].btType := 38;
                10: m_PetInfo[1].btType := 39;
                11: m_PetInfo[1].btType := 44;
                12: m_PetInfo[1].btType := 45;
                13: m_PetInfo[1].btType := 46;
                14: m_PetInfo[1].btType := 41;
                15: m_PetInfo[1].btType := 47;
              end;
            end;
          end;
          nCode := 8;
          SendPetInfo($03);
          nCode := 9;
        end;
      end else begin
        nCode := 10;
        m_PackPet := nil;
        m_nSlaveKillMonCount := m_PetInfo[1].nMakeIndex;
        m_PetInfo[1].nMakeIndex := 0;
        SysMsg('灵兽守摊结束', c_Red, t_Hint);
      end;
    end;
    //凤凰探宝
    if m_PetInfo[4].nMakeIndex <> 0 then begin
      nCode := 11;
      if GetUserItemByMakeIndex(m_PetInfo[4].nMakeIndex, UserItem) >= 0 then begin
        nCode := 12;
        tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        if (DateTimeToWolTIme(Now) - tm) < 4 * 86400 then begin
          nCode := 13;
          m_PetInfo[4].wLevel := MakeWord(UserItem.btValue[4], UserItem.btValue[5]);
          m_PetInfo[4].btType := 0;
          m_PetInfo[4].btReLive := UserItem.btValue[9];
          m_PetInfo[4].btRideFightSpeed := UserItem.btRideSpeed;
          m_PetInfo[4].btAttack := UserItem.btExtra.btAttack;                                       //骑战技能攻击距离
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if (StdItem <> nil) then begin
            if (UserItem.btValue[9] > 0) then begin
              nCode := 14;
              case StdItem.AniCount of
                0: m_PetInfo[4].btType := 10 + UserItem.btValue[8];
                1: m_PetInfo[4].btType := 13 + UserItem.btValue[8];
                2: m_PetInfo[4].btType := 16 + UserItem.btValue[8];
                3: m_PetInfo[4].btType := 19 + UserItem.btValue[8];
                4: m_PetInfo[4].btType := 22 + UserItem.btValue[8];
                5: m_PetInfo[4].btType := 25 + UserItem.btValue[8];
                6: m_PetInfo[4].btType := 28 + UserItem.btValue[8];
                7: m_PetInfo[4].btType := 31 + UserItem.btValue[8];
                8: m_PetInfo[4].btType := 34 + UserItem.btValue[8];
                9: m_PetInfo[4].btType := 37 + UserItem.btValue[8];
                10: m_PetInfo[4].btType := 38 + UserItem.btValue[8];
                11: m_PetInfo[4].btType := 43 + UserItem.btValue[8];
                12: m_PetInfo[4].btType := 44 + UserItem.btValue[8];
                13: m_PetInfo[4].btType := 45 + UserItem.btValue[8];
                14: m_PetInfo[4].btType := 40 + UserItem.btValue[8];
                15: m_PetInfo[4].btType := 46 + UserItem.btValue[8];
              end;
            end else begin
              nCode := 15;
              case StdItem.AniCount of
                0: m_PetInfo[4].btType := 11;
                1: m_PetInfo[4].btType := 14;
                2: m_PetInfo[4].btType := 17;
                3: m_PetInfo[4].btType := 20;
                4: m_PetInfo[4].btType := 23;
                5: m_PetInfo[4].btType := 26;
                6: m_PetInfo[4].btType := 29;
                7: m_PetInfo[4].btType := 32;
                8: m_PetInfo[4].btType := 35;
                9: m_PetInfo[4].btType := 38;
                10: m_PetInfo[4].btType := 39;
                11: m_PetInfo[4].btType := 44;
                12: m_PetInfo[4].btType := 45;
                13: m_PetInfo[4].btType := 46;
                14: m_PetInfo[4].btType := 41;
                15: m_PetInfo[4].btType := 47;
              end;
            end;
          end;
          nCode := 16;
          SendPetInfo($09);
          nCode := 17;
        end else begin
          nCode := 18;
          ClientPhoenixSearch(m_PetInfo[4].nMakeIndex, 1);                                          //召回凤凰
          nCode := 19;
        end;
      end else begin
        m_PetInfo[4].nMakeIndex := 0;
      end;
    end;
    nCode := 20;
    //魂佑附体
    if m_PetInfo[5].nMakeIndex <> 0 then begin
      if GetUserItemByMakeIndex(m_PetInfo[5].nMakeIndex, UserItem) >= 0 then begin
        nCode := 21;
        tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        if (DateTimeToWolTIme(Now) - tm) < 4 * 86400 then begin
          nCode := 22;
          m_PetInfo[5].wLevel := MakeWord(UserItem.btValue[4], UserItem.btValue[5]);
          m_PetInfo[5].btType := 0;
          m_PetInfo[5].btReLive := UserItem.btValue[9];
          m_PetInfo[5].btRideFightSpeed := UserItem.btRideSpeed;
          m_PetInfo[5].boUnWater := (UserItem.btItemExt[24] <> 0);                                  //避水灵性
          m_PetInfo[5].btSoul := byte(UserItem.btItemExt[29] >= 2);                                 //魂佑灵兽
          m_PetInfo[5].btAttack := UserItem.btExtra.btAttack;                                       //骑战技能攻击距离
          nCode := 23;
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if (StdItem <> nil) then begin
            nCode := 24;
            if (UserItem.btValue[9] > 0) then begin
              nCode := 25;
              case StdItem.AniCount of
                0: m_PetInfo[5].btType := 10 + UserItem.btValue[8];
                1: m_PetInfo[5].btType := 13 + UserItem.btValue[8];
                2: m_PetInfo[5].btType := 16 + UserItem.btValue[8];
                3: m_PetInfo[5].btType := 19 + UserItem.btValue[8];
                4: m_PetInfo[5].btType := 22 + UserItem.btValue[8];
                5: m_PetInfo[5].btType := 25 + UserItem.btValue[8];
                6: m_PetInfo[5].btType := 28 + UserItem.btValue[8];
                7: m_PetInfo[5].btType := 31 + UserItem.btValue[8];
                8: m_PetInfo[5].btType := 34 + UserItem.btValue[8];
                9: m_PetInfo[5].btType := 37 + UserItem.btValue[8];
                10: m_PetInfo[5].btType := 38 + UserItem.btValue[8];
                11: m_PetInfo[5].btType := 43 + UserItem.btValue[8];
                12: m_PetInfo[5].btType := 44 + UserItem.btValue[8];
                13: m_PetInfo[5].btType := 45 + UserItem.btValue[8];
                14: m_PetInfo[5].btType := 40 + UserItem.btValue[8];
                15: m_PetInfo[5].btType := 46 + UserItem.btValue[8];
              end;
            end else begin
              nCode := 26;
              case StdItem.AniCount of
                0: m_PetInfo[5].btType := 11;
                1: m_PetInfo[5].btType := 14;
                2: m_PetInfo[5].btType := 17;
                3: m_PetInfo[5].btType := 20;
                4: m_PetInfo[5].btType := 23;
                5: m_PetInfo[5].btType := 26;
                6: m_PetInfo[5].btType := 29;
                7: m_PetInfo[5].btType := 32;
                8: m_PetInfo[5].btType := 35;
                9: m_PetInfo[5].btType := 38;
                10: m_PetInfo[5].btType := 39;
                11: m_PetInfo[5].btType := 44;
                12: m_PetInfo[5].btType := 45;
                13: m_PetInfo[5].btType := 46;
                14: m_PetInfo[5].btType := 41;
                15: m_PetInfo[5].btType := 47;
              end;
            end;
          end;
          nCode := 27;
          m_boBeast := True;
          UserItem.btItemExt[29] := 3;
          SendUpdateItem(UserItem, False);
          SendDefMessage(1283, Integer(Self), m_nCurrX, m_nCurrY, 65535, '');
          SendRefMsg(RM_510, 1, 0, 170, 0, '');
          SendPetInfo($0A);
          RecalcPetSoulAbilitys;
          nCode := 28;
        end else begin
          nCode := 29;
          m_PetInfo[5].nMakeIndex := 0;
          UserItem.btItemExt[29] := 2;
          SendUpdateItem(UserItem, False);
          nCode := 30;
        end;
        nCode := 31;
        RecalcAbilitys();                                                                           //重新计算属性
        SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
        SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
        nCode := 32;
      end;
    end;
  except
    on E: Exception do
      MainOutMessage(Format(sExceptionMsg, [m_sCharName, nCode]));
  end;
end;

//检测是否有 潜行

procedure TPlayObject.CheckProwlMagic();
var
  i                                     : Integer;
  BaseObject                            : TBaseObject;
  VisibleBaseObject                     : pTVisibleBaseObject;
begin
  if m_boObMode and (m_wStatusTimeArr[STATE_PROWL {19}] > 0) then begin
    m_boObMode := False;
    for i := 0 to m_VisibleActors.Count - 1 do begin
      VisibleBaseObject := pTVisibleBaseObject(m_VisibleActors.Items[i]);
      BaseObject := TBaseObject(VisibleBaseObject.BaseObject);
      if BaseObject.m_btRaceServer = RC_PLAYOBJECT then
        TPlayObject(BaseObject).SendMsg(Self,
          RM_TURN, m_btDirection, m_nCurrX, m_nCurrY, CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), GetShowName);
    end;
    m_wStatusTimeArr[STATE_PROWL {19}] := 1;
  end;
end;

//检测用户身上过期装备

function TPlayObject.CheckUserItemTimeOut(UserItem: pTUserItem; StdItem: pTStdItem): Boolean;
var
  tm, nowtm                             : DWORD;
begin
  Result := False;
  tm := 0;
  if (StdItem.StdMode = 18) or ((StdItem.StdMode = 29) and (StdItem.Shape = 150)) then begin
    if (StdItem.StdMode = 29) and (StdItem.Shape = 150) and (StdItem.AniCount = 1) then
      tm := MakeLong(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]), MakeWord(UserItem.btItemExt[2], UserItem.btItemExt[3]))
    else
      tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
    if (tm = 0) then begin                                                                          //第一次使用
      tm := DateTimeToWolTIme(Now);
      if (StdItem.StdMode = 29) and (StdItem.Shape = 150) and (StdItem.AniCount = 1) then begin
        UserItem.btItemExt[0] := LoByte(LoWord(tm));
        UserItem.btItemExt[1] := HiByte(LoWord(tm));
        UserItem.btItemExt[2] := LoByte(HiWord(tm));
        UserItem.btItemExt[3] := HiByte(HiWord(tm));
      end else begin
        UserItem.btValue[0] := LoByte(LoWord(tm));
        UserItem.btValue[1] := HiByte(LoWord(tm));
        UserItem.btValue[2] := LoByte(HiWord(tm));
        UserItem.btValue[3] := HiByte(HiWord(tm));
      end;
      SendUpdateItem(UserItem);
    end else begin
      nowtm := DateTimeToWolTIme(Now);
      if (StdItem.Shape = 150) and (tm + Round(UserItem.Dura / 1000) * 86400 < nowtm) then begin
        Result := True;
      end;
    end;
  end else if (StdItem.StdMode = 6) and (StdItem.Shape = 20) and (StdItem.AniCount > 0) then begin
    tm := MakeLong(MakeWord(UserItem.btItemExt2[146], UserItem.btItemExt2[147]), MakeWord(UserItem.btItemExt2[148], UserItem.btItemExt2[149]));
    if (tm = 0) then begin
      tm := DateTimeToWolTIme(Now);
      UserItem.btItemExt2[146] := LoByte(LoWord(tm));
      UserItem.btItemExt2[147] := HiByte(LoWord(tm));
      UserItem.btItemExt2[148] := LoByte(HiWord(tm));
      UserItem.btItemExt2[149] := HiByte(HiWord(tm));
      SendUpdateItem(UserItem);
    end else begin
      nowtm := DateTimeToWolTIme(Now);
      if (tm + Round(StdItem.AniCount * 60) < nowtm) then begin
        Result := True;
      end;
    end;
  end;
end;

procedure TPlayObject.ClearEvilFollower(nCode: Integer);
var
  i                                     : Integer;
  BaseObject                            : TBaseObject;
  boChg                                 : Boolean;
begin
  boChg := False;
  for i := m_SlaveList.Count - 1 downto 0 do begin
    BaseObject := TBaseObject(m_SlaveList[i]);
    if (BaseObject.m_btRaceServer = RC_EVIL) and (BaseObject.m_nSlaveType <> -2) then begin
      case nCode of
        0: begin
            BaseObject.m_dwEvilUniQueSkillTick := GetTickCount;                                     //心魔绝杀
            BaseObject.m_nCharStatus := BaseObject.GetCharStatus();
            BaseObject.StatusChanged();
          end;
        1: begin                                                                                    //心魔红名
            BaseObject.m_btNameColor := $F9;
            BaseObject.RefNameColor;
            BaseObject.RefShowName;
          end;
        2: begin                                                                                    //冻结心魔
            BaseObject.MakePosion(POISON_DONTMOVE, 6000, 0);
          end;
        3: begin                                                                                    //释放心魔
            SysMsg(Format('你的宠物(%s)叛变了', [BaseObject.m_sFilterCharName]), c_Pink, t_Hint);
            BaseObject.m_Master := nil;
            BaseObject.m_boSuperMan := False;
            BaseObject.m_wStatusTimeArr[POISON_DONTMOVE] := 1;
            BaseObject.RefNameColor;
            BaseObject.RefShowName;
            BaseObject.HealthSpellChanged;
            m_SlaveList.Delete(i);
            SendDefMessage(CM_RECALLEVIL, 0, 1, 0, 0, '');
            m_nEvilFollowerPower := 0;
            boChg := True;
          end;
        4: begin                                                                                    //解除心魔冻结
            if BaseObject.m_wStatusTimeArr[POISON_DONTMOVE] > 0 then begin
              BaseObject.m_wStatusTimeArr[POISON_DONTMOVE] := 1;
            end;
            if (BaseObject.m_btNameColor <> $FF) then begin
              BaseObject.m_btNameColor := $FF;
              BaseObject.RefNameColor;
              BaseObject.RefShowName;
            end;
            BaseObject.HealthSpellChanged;
          end;
        5: begin
            BaseObject.HealthSpellChanged;
          end;
        6: begin
            BaseObject.MakeGhost;
            m_SlaveList.Delete(i);
            SendDefMessage(CM_RECALLEVIL, 0, 1, 0, 0, '');
            m_nEvilFollowerPower := 0;
            boChg := True;
          end;
      end;
    end;
  end;
  if boChg then ClientQueryEvilFollower();
end;

//清除人物状态时间标志

procedure TPlayObject.ClearStatusTime;
begin
  FillChar(m_wStatusTimeArr, SizeOf(TStatusTime), 0);
end;

{查看棋座??}

procedure TPlayObject.ClickQueryMsg(NPCID: Integer; btnid: Integer);
  function CheckBagItemDura(sItemName: string; nItemCount: Integer): Integer;
  var
    i, nCurCount                        : Integer;
    UserItem                            : pTUserItem;
    StdItem                             : pTStdItem;
    nIndex                              : Integer;
  begin
    Result := 0;
    if sItemName = '' then Exit;
    if nItemCount <= 0 then Exit;
    nIndex := UserEngine.GetStdItemIdx(sItemName);
    if nIndex > 0 then begin
      StdItem := UserEngine.GetStdItem(nIndex);
      if StdItem = nil then Exit;

      for i := m_ItemList.Count - 1 downto 0 do begin
        if nItemCount <= 0 then Break;
        UserItem := pTUserItem(m_ItemList.Items[i]);
        if UserItem = nil then Exit;
        if UserItem.wIndex = nIndex then begin

          nCurCount := 0;
          if UserItem.Dura > nItemCount then begin
            nCurCount := nItemCount;
          end else begin
            nCurCount := UserItem.Dura;
          end;
          Dec(nItemCount, nCurCount);
          Inc(Result, nCurCount);
        end;
      end;
    end;
  end;
  function TakeBagItemDura(sItemName: string; nItemCount: Integer): Integer;
  var
    i, nCurCount                        : Integer;
    UserItem                            : pTUserItem;
    StdItem                             : pTStdItem;
    nIndex                              : Integer;
  begin
    Result := 0;
    if sItemName = '' then Exit;
    if nItemCount <= 0 then Exit;
    nIndex := UserEngine.GetStdItemIdx(sItemName);
    if nIndex > 0 then begin
      StdItem := UserEngine.GetStdItem(nIndex);
      if StdItem = nil then Exit;

      for i := m_ItemList.Count - 1 downto 0 do begin
        if nItemCount <= 0 then Break;
        UserItem := pTUserItem(m_ItemList.Items[i]);
        if UserItem = nil then Exit;
        if UserItem.wIndex = nIndex then begin

          if StdItem.boGameLog = 1 then
            AddGameDataLog('10' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              sItemName + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              m_sCharName);

          nCurCount := 0;
          if UserItem.Dura > nItemCount then begin
            nCurCount := nItemCount;
            Dec(UserItem.Dura, nItemCount);
            SendUpdateItem(UserItem);
          end else begin
            nCurCount := UserItem.Dura;
            SendDelItems(UserItem);
            if UserItem.MakeIndex = m_nEatItemMakeIndex then
              m_nEatItemMakeIndex := 0;
            Dispose(UserItem);
            m_ItemList.Delete(i);
          end;
          Dec(nItemCount, nCurCount);
          Inc(Result, nCurCount);
        end;
      end;
    end;
  end;
var
  NPC                                   : TNormNpc;
  nMakeIndex                            : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  NPC := UserEngine.FindMerchant(TObject(NPCID));
  if NPC = nil then NPC := UserEngine.FindNPC(TObject(NPCID));
  if NPC <> nil then begin
    if NPC = nil then Exit;
    if m_sNextLabel <> '' then begin
      try
        NPC.GotoLable(Self, m_sNextLabel + IntToStr(btnid), False);
      except

      end;
    end;
  end else begin
    //破碎物品修复
    if (Pos('Fracture', m_sNextLabel) > 0) and (btnid = 1) then begin
      nMakeIndex := Str_ToInt(Copy(m_sNextLabel, 10, Length(m_sNextLabel)), 0);
      GetUserItemByMakeIndex(nMakeIndex, UserItem);
      if UserItem <> nil then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem <> nil then begin
          if CheckBagItemDura('五色晶石', StdItem.Broken) >= StdItem.Broken then begin
            UserItem.btItemExt[4] := 0;
            UserItem.Dura := UserItem.DuraMax;
            SendUpdateItem(UserItem);
            TakeBagItemDura('五色晶石', StdItem.Broken);
          end else SendMsg(Self, RM_SYSMESSAGE, 0, 255, 253, 0,
              '你包裹中没有五色晶石或者其持久不够,请到商城购买后再进行修复。');
        end;
      end;
    end;
  end;
end;

resourcestring
  sTreasureName                         = '灵犀宝盒';
  sHaveNoNimBusPoint                    = '你身上没有这么多灵力,无法为灵犀宝盒注入灵力。';
  sNeedInjectPower                      = '灵犀宝盒的灵力耗尽,不能向宝盒中存入物品和从宝盒中取出物品,需要重新冲入灵力。';
  sCanNotInTreasureBox                  = '灵犀宝盒储物能力有限,不能保存%s';

procedure TPlayObject.ClientActivationTreasureBox();
var
  UserItem                              : TUserItem;
  pStdItem                              : pTStdItem;
  tm                                    : DWORD;
  d                                     : TDateTime;
begin
  if m_boGhost or
    m_boDeath or
    (m_TreasureBoxItem <> nil) or
    (m_TreasureBoxItemList.Count > 0) then
    Exit;

  if (m_Abil.wNimBusPoint < 10) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sHaveNoNimBusPoint);
    Exit;
  end;

  if UserEngine.CopyToUserItemFromName(sTreasureName, @UserItem) then begin
    Dec(m_Abil.wNimBusPoint, 10);
    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    tm := DateTimeToWolTimeEx(Now);
    Move(tm, UserItem.btValue[0], 4);                                                               //激活时间
    tm := DateTimeToWolTimeEx(AddDateTimeOfDay(Now, 8));                                            //到期时间
    Move(tm, UserItem.btValue[4], 4);
    UserItem.Dura := 0;
    UserItem.DuraMax := 10;                                                                         //开通的格子数量
    New(m_TreasureBoxItem);
    m_TreasureBoxItem^ := UserItem;
    ClientQueryTreasureBoxItems(False);
  end else begin
    SysMsg('本功能尚未开放,敬请期待!', c_Red, t_Hint);
  end;
end;

function TPlayObject.GetEvilRecByMakeIndex(nItemMakeIndex: Integer): pTEvil;
begin

end;

procedure TPlayObject.DelEvilRec(nItemMakeIndex: Integer; DisMem: Boolean = True);
begin

end;

{增加装备装备镇魔值}

procedure TPlayObject.ClientAddAntiEvilPower(nWhere: word; nMakeIndex,
  nAntiEvilItem: Integer);
var
  i                                     : Integer;
  UserItem, Item                        : pTUserItem;
  StdItem, StdItem34                    : pTStdItem;
  nA, nB                                : word;
  boOk                                  : Boolean;
begin
  boOk := False;
  nA := 0;
  nB := 0;
  if not m_boCanUseItem then Exit;
  if (not m_boDeath) and (not m_boGhost) then begin
    GetUserItemByMakeIndex(nAntiEvilItem, UserItem);
    if nWhere = 256 then begin
      GetUserItemByMakeIndex(nMakeIndex, Item)
    end else begin
      Item := nil;
      if (nWhere < MAX_HUMITEM_COUNT) and (m_UseItems[nWhere].wIndex > 0) then
        Item := @m_UseItems[nWhere];                                                                //装备
    end;
    if (UserItem <> nil) and (Item <> nil) and (Item.MakeIndex = nMakeIndex) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);                                            //镇魔符
      StdItem34 := UserEngine.GetStdItem(Item.wIndex);                                              //装备
      if (StdItem34 <> nil) and (StdItem <> nil) then begin
        if UserItem.Dura > 0 then begin
          {镇魔值}
          if (Item.Evil.wPower >= 65000) then begin
            SysMsg(Format('%s的镇魔力量已经很强了,不需要在增加镇魔值!', [StdItem34.FilterName]), c_Red, t_Hint);
            Exit;
          end;
          Item.Evil.wPower := _MIN(65000, Item.Evil.wPower + StdItem.AC * 1000);
          {黑暗魔力}
          if g_Config.boAntiEvilItemAddGloomPoint then begin
            nA := StdItem.AC * g_Config.nAddGloomPointRate + Random(g_Config.nAddGloomRandomPoint);
            Move(Item.btItemExt[0], nB, 2);
            nA := _MIN(High(word), nA + nB);
            Move(nA, Item.btItemExt[0], 2);
          end;
          {触发脚本}
          m_sScriptParam[0] := Item.Evil.sName;
          m_sScriptParam[1] := IntToStr(nWhere);
          m_sScriptParam[2] := IntToStr(Item.MakeIndex);
          m_sScriptParam[3] := IntToStr(UserItem.MakeIndex);
          m_sScriptParam[4] := StdItem34.Name;
          m_sScriptParam[5] := StdItem.Name;
          ExecuteScript(g_FunctionNPC, '@增加镇魔值');
          SendUpdateItem(Item);
          if nWhere = 256 then
            SendDefMessage(SM_ANTIEVILPOWER, Item.MakeIndex, Item.Evil.wPower, nWhere, 0, '');      //刷新镇魔值
          if not boOk then begin
            if (Item.Evil.wPower >= 65000) then
              SysMsg(Format('%s的镇魔值已满,黑暗魔力进一步提升!', [StdItem34.FilterName]), c_Red, t_Hint)
            else
              SysMsg(Format('%s的镇魔值和黑暗魔力同时获得了提升!', [StdItem34.FilterName]), c_Red, t_Hint);
          end;
          SendDefMessage(SM_EAT_OK, 0, 0, 0, 0, '');
          Dec(UserItem.Dura);
          SendUpdateItem(UserItem);
        end;
      end;
      if UserItem.Dura <= 0 then begin
        SendDelItems(UserItem);
        DelBagItem(UserItem.MakeIndex, UserEngine.GetStdItemName(UserItem.wIndex));
      end;
    end;
  end;
end;

//添加要交易的物品

procedure TPlayObject.ClientAddDealItem(nItemIdx: Integer; sItemName: string);
var
  i, ii                                 : Integer;
  bo11                                  : Boolean;
  UserItem                              : pTUserItem;
  sName                                 : string;
  StdName                               : string;
  tm                                    : DWORD;
  StdItem                               : pTStdItem;
begin
  if (m_DealCreat = nil) or (not m_boDealing) then Exit;
  bo11 := False;
  if not m_DealCreat.m_boDealOK then begin
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := m_ItemList.Items[i];
      if UserItem.MakeIndex = nItemIdx then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem = nil then Break;
        //物品控制-禁止交易物品
        if CheckSPCode(StdItem.SPCode, SP_DISABLESALE) or
          ((UserItem.btItemExt[4] and EX_BIND) = EX_BIND) then begin
          bo11 := False;
          Break;
        end;

        {魂佑灵兽禁止交易}
        if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then
          Break;

        {已放出豹禁止交易}
        if IsDownPetItem(UserItem.MakeIndex) then
          Break;

        {自定义物品名称}
        sName := '';
        ItemUnit.GetCustomItemName(UserItem, sName);

        if (CompareText(sItemName, sName) = 0) and (m_DealItemList.Count < 12) then begin
          m_DealItemList.Add(UserItem);
          TPlayObject(Self).SendAddDealItem(UserItem);
          m_ItemList.Delete(i);
          bo11 := True;
          Break;
        end;
      end;
    end;
  end;
  if not bo11 then
    SendDefMessage(SM_DEALADDITEM_FAIL, 0, 0, 0, 0, '');
end;

{附加心魔到装备}

procedure TPlayObject.ClientAddEvilToItem(nWhere: word; nMakeIndex, BottleIndex: Integer);
var
  boOk                                  : Boolean;
  UserItem, BottleItem                  : pTUserItem;
  StdItem                               : pTStdItem;
begin
  boOk := False;
  if not m_boCanUseItem then Exit;
  if (not m_boDeath) and (not m_boGhost) then begin
    GetUserItemByMakeIndex(BottleIndex, BottleItem);
    GetUserItemByMakeIndex(nMakeIndex, UserItem);
    if (UserItem <> nil) and (BottleItem <> nil) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        if (BottleItem.Evil.sName = '') or (BottleItem.Evil.MakeIndex = 0) then begin
          SysMsg('无法从玉净瓶中感应到心魔气息,不能附魔!', c_Red, t_Hint);
          Exit;
        end;
        if CheckSPCode(StdItem.SPCode, SP_DISABLEGETEVIL) then begin                                //物品控制-禁止附魔
          SysMsg('该物品不能用于被附魔!', c_Red, t_Hint);
          Exit;
        end;
        if BottleItem.Evil.wPower < 2000 then begin
          SysMsg('玉净瓶的镇魔力量太弱,不能附魔!', c_Red, t_Hint);
          Exit;
        end else begin
          m_sScriptParam[0] := BottleItem.Evil.sName;
          m_sScriptParam[1] := IntToStr(nWhere);
          m_sScriptParam[2] := IntToStr(UserItem.MakeIndex);
          m_sScriptParam[3] := IntToStr(BottleItem.MakeIndex);
          m_sScriptParam[4] := UserEngine.GetStdItemName(UserItem.wIndex);
          m_sScriptParam[5] := UserEngine.GetStdItemName(BottleItem.wIndex);

          boOk := ExecuteScript(g_FunctionNPC, '@装备附魔');
          {直接给装备附魔}
          if not boOk then
            AddEvilToItemB(nWhere, nMakeIndex, BottleIndex);
        end;
      end;
    end;
  end;
end;

//添加好友

procedure TPlayObject.ClientAddFriend(FriendName: string);
var
  i, j                                  : Integer;
  s                                     : string;
  human                                 : TPlayObject;
  C                                     : Char;
begin
  //检查好友数量,不能超过100个
  if m_FriendsList.Count >= _MIN(g_Config.nFriendCount, MAX_FRIENDS_COUNT) then begin
    SysMsg('你的好友数量已经达到最大,请删除一部分后再添加。', c_Red, t_Hint);
    Exit;
  end;

  //首先检查是否在已经有的好友名单中
  for i := 0 to m_FriendsList.Count - 1 do begin
    if m_FriendsList[i] = FriendName then begin
      //已经在好友列表中
      SendDefMessage(SM_RefuseAddFriend, 5, 0, 0, 0, FriendName);
      Exit;
    end;
  end;
  human := UserEngine.GetPlayObject(FriendName);
  //对方在线
  if (human <> nil) and (not human.m_boDeath) and (not human.m_boGhost) then begin
    //检查对方是否允许加为好友
    if human.m_boAllowAddFriend then begin
      human.SendDefMessage(SM_ReqAddFriend, 2, 0, 0, 0, m_sCharName);
      m_sScriptParam[0] := FriendName;
      ExecuteScript(g_ManageNPC, '@人脉_添加好友');
    end else
      SysMsg(FriendName + '玩家暂时不能被添加为好友,添加失败。', c_Red, t_Hint);
  end else begin                                                                                    //名字错误,或者不在线
    SendDefMessage(SM_RefuseAddFriend, 2, 0, 0, 0, FriendName);
  end;
end;

//增加队伍成员

procedure TPlayObject.ClientAddGroupMember(sHumName: string);                                       //004DCE48
var
  PlayObject                            : TPlayObject;
  i                                     : Integer;
begin
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if m_GroupOwner <> Self then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -1, 0, 0, 0, '');
    Exit;
  end;
  if m_GroupMembers.Count > g_Config.nGroupMembersMax then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -5, 0, 0, 0, '');
    Exit;
  end;
  if (PlayObject = nil) or (PlayObject = Self) or PlayObject.m_boDeath or
    PlayObject.m_boGhost then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;

  if (PlayObject.m_PEnvir <> m_PEnvir) then begin                                                   //增加控制:只有在同一地图才可以加入组队
    SendDefMessage(SM_GROUPADDMEM_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;

  if (PlayObject.m_GroupOwner <> nil) then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -3, 0, 0, 0, '');
    Exit;
  end;

  if (PlayObject.m_boPneuma) then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;

  //增加判断,组队中不允许同名队员  xyfate 2005/10/19
  for i := 0 to m_GroupMembers.Count - 1 do begin
    if m_GroupMembers[i] = sHumName then begin
      SendDefMessage(SM_GROUPADDMEM_FAIL, -2, 0, 0, 0, '');
      Exit;
    end;
  end;

  if (not PlayObject.m_boAllowGroup) then begin
    SendDefMessage(SM_GROUPADDMEM_FAIL, -4, 0, 0, 0, '');
    Exit;
  end;
  m_GroupMembers.AddObject(sHumName, PlayObject);
  PlayObject.JoinGroup(Self);
  SendDefMessage(SM_GROUPADDMEM_OK, 0, 0, 0, 0, '');
  SendGroupMembers();
  ExecuteScript(g_FunctionNPC, '@_加入队伍');
end;

//调整属性值

procedure TPlayObject.ClientAdjustBonus(nPoint: Integer; sMsg: string);
//004DF804
var
  BonusAbil                             : TNakedAbility;
  nTotleUsePoint                        : Integer;
begin
  FillChar(BonusAbil, SizeOf(TNakedAbility), #0);
  DeCodeBuffer(sMsg, @BonusAbil, SizeOf(TNakedAbility));

  nTotleUsePoint := BonusAbil.DC +
    BonusAbil.MC +
    BonusAbil.SC +
    BonusAbil.AC +
    BonusAbil.MAC +
    BonusAbil.HP +
    BonusAbil.MP +
    BonusAbil.Hit +
    BonusAbil.Speed +
    BonusAbil.X2;

  if (nPoint + nTotleUsePoint) = m_nBonusPoint then begin
    m_nBonusPoint := nPoint;
    Inc(m_BonusAbil.DC, BonusAbil.DC);
    Inc(m_BonusAbil.MC, BonusAbil.MC);
    Inc(m_BonusAbil.SC, BonusAbil.SC);
    Inc(m_BonusAbil.AC, BonusAbil.AC);
    Inc(m_BonusAbil.MAC, BonusAbil.MAC);
    Inc(m_BonusAbil.HP, BonusAbil.HP);
    Inc(m_BonusAbil.MP, BonusAbil.MP);
    Inc(m_BonusAbil.Hit, BonusAbil.Hit);
    Inc(m_BonusAbil.Speed, BonusAbil.Speed);
    Inc(m_BonusAbil.X2, BonusAbil.X2);

    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  end else begin
    SysMsg('非法数据调整!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.ClientDECOMPOSE(nParam, nMakeIndex: Integer);
var
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
begin
  m_sScriptParam[40] := '';
  m_sScriptParam[41] := '';
  if m_boGhost or m_boDeath then Exit;

  if nMakeIndex > 0 then begin
    GetUserItemByMakeIndex(nMakeIndex, UserItem);
    if (UserItem <> nil) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        m_sScriptParam[40] := StdItem.Name;
        m_sScriptParam[41] := IntToStr(nMakeIndex);
        case nParam of
          1: ExecuteScript(g_FunctionNPC, '@拆卸装备');
          0: ExecuteScript(g_FunctionNPC, '@拆卸开始');
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.ClientGEMREMOVE(nWhere, nMakeIndex: Integer);
var
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  ANpc                                  : TNormNpc;
begin
  m_sScriptParam[40] := '';
  m_sScriptParam[41] := '';
  m_sScriptParam[42] := '';
  if m_boGhost or m_boDeath then Exit;
  if m_ClickNPC = nil then Exit;
  ANpc := TNormNpc(m_ClickNPC);

  if nMakeIndex > 0 then begin
    GetUserItemByMakeIndex(nMakeIndex, UserItem);
    if (UserItem <> nil) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        m_sScriptParam[40] := StdItem.Name;
        m_sScriptParam[41] := IntToStr(nMakeIndex);
        m_sScriptParam[42] := IntToStr(nWhere);
        if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
          ANpc.GotoLable(Self, '@@gemremove', False);
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.ClientYiWangDan(nMakeIndex: Integer; sSkillName: string);
var
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  Magic                                 : pTMagic;
  UserMagic                             : pTUserMagic;
begin
  if nMakeIndex > 0 then begin
    GetUserItemByMakeIndex(nMakeIndex, UserItem);
    if (UserItem <> nil) then begin
      DelItemSkill(sSkillName);
      SysMsg(Format('技能%s已删除。', [sSkillName]), c_Green, t_Hint);
      RecalcAbilitys();
      SendDelItems(UserItem);
      DelBagItem(UserItem.MakeIndex, '');
    end;
  end;
end;

procedure TPlayObject.ClientAllotGuildGold(sName: string; nGold: Integer);
var
  Hum                                   : TPlayObject;
begin
  if m_boGhost or m_boDeath then Exit;
  if m_MyGuild = nil then Exit;
  if (TGuild(m_MyGuild).GetChiefName <> m_sCharName) then begin
    SysMsg('你不是行会会长,没有权限执行此操作!', c_Red, t_Hint);
    Exit;
  end;
  if (nGold <= 0) or (nGold > TGuild(m_MyGuild).dwGuildGold) then begin
    SysMsg('你输入的分配数量错误,请重新输入!', c_Red, t_Hint);
    Exit;
  end;
  Hum := UserEngine.GetPlayObject(sName);
  if (Hum <> nil) and (not Hum.m_boGhost) and (not Hum.m_boDeath) then begin
    if TGuild(m_MyGuild).IsMember(sName) then begin
      TGuild(m_MyGuild).dwGuildGold := TGuild(m_MyGuild).dwGuildGold - nGold;
      //      SendDefMessage(SM_ALLOTGUILDGOLD, nGold, 0, 0, 0, sName);
      Inc(Hum.m_nGuildGold, nGold);
      Hum.GuildGoldChanged;
      SendGuildTowerRes;
      SysMsg('你成功分配了' + IntToStr(nGold) + '行会公共银两给' + sName + '。', c_Red, t_Hint);
      Hum.SysMsg(m_sCharName + '分配给你' + IntToStr(nGold) + '行会公共银两。', c_Red, t_Hint);
    end else
      SysMsg(sName + '已经不是本行会成员,无法分配行会银两!', c_Red, t_Hint);
  end else
    SysMsg(sName + '已经不在线了,无法分配行会银两!', c_Red, t_Hint);
end;

procedure TPlayObject.ClientAskForGuildOfficial(nRankNo: Integer; sData: string);
var
  sOfficialName                         : string;
  Official                              : TPlayObject;
  nTowerGrade                           : Integer;
begin
  if (not (nRankNo in [1..10])) or (sData = '') then Exit;
  if m_MyGuild = nil then Exit;
  nTowerGrade := TGuild(m_MyGuild).btTowerGrade;
  nTowerGrade := _MIN(10, nTowerGrade);
  if (nTowerGrade <= 0) or (nGuildOfficialCount[nTowerGrade][nRankNo] = 0) or (TGuild(m_MyGuild).GetRankMemberCount(nRankNo) >= nGuildOfficialCount[nTowerGrade][nRankNo]) then begin
    SysMsg('当前职位尚未设立,无法任命该职位!', c_Red, t_Hint);
    Exit;
  end;
  if (TGuild(m_MyGuild).GetChiefName <> m_sCharName) then begin
    SysMsg('你不是行会会长,没有权限执行此操作!', c_Red, t_Hint);
    Exit;
  end;
  sData := GetValidStr3(sData, sOfficialName, ['/']);
  if (sOfficialName <> '') then Official := UserEngine.GetPlayObject(sOfficialName);
  if (sData <> '') then begin
    TGuild(m_MyGuild).GetOfficial(99, g_Config.sGuildMemberRank, sData);                            //撤职查办
  end;
  if (Official <> nil) then begin
    if (Official = Self) then begin
      SysMsg('不可以任命自己!', c_Red, t_Hint);
      Exit;
    end;
    if (Official.m_btRaceServer <> RC_PLAYOBJECT) or (Official.m_boPneuma) then begin
      SysMsg('任命失败!!!', c_Red, t_Hint);
      Exit;
    end;
    if Official.m_MyGuild = m_MyGuild then begin
      if Official.m_nGuildGold >= nGuildOfficialPrice[nRankNo] then begin
        Official.SendDefMessage(SM_QUESTGUILDOFFICIAL, 50, nRankNo, LoWord(Integer(Official)), HiWord(Integer(Official)), m_sCharName);
        m_GuildOfficial := nRankNo;
      end else
        SysMsg(sOfficialName + '行会银两不足' + IntToStr(nGuildOfficialPrice[nRankNo]) + '个,无法任命该职位!', c_Red, t_Hint);
    end else
      SysMsg(sOfficialName + '非本行会成员,无法任命该职位!', c_Red, t_Hint);
  end else
    SysMsg(sOfficialName + '不在线,无法任命该职位!', c_Red, t_Hint);
end;

procedure TPlayObject.ClientCallTiger();
const
  sTigerName                            : string = '啸天虎';
  sDragonName                           : array[0..2] of string = ('金甲龙王', '紫衫龙王', '碧铠龙王');
var
  StdItem                               : pTStdItem;
  dwNowWolTime                          : DWORD;
  i, nReCallTime                        : Integer;
  sName                                 : string;
begin
  if m_boGhost or m_boDeath or m_boPneuma then Exit;
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王盾的

  if (m_TorDDM.Tiger.DB.Dragon > 0) then sName := '龙' else sName := '虎';

  if m_PEnvir.m_MapFlag.boNOTIGER then begin
    SysMsg(Format('本地图禁止释放%s王。', [sName]), c_Red, t_Hint);
    Exit;
  end;

  //召唤虎王
  if m_Tiger = nil then begin
    StdItem := nil;
    if (m_UseItems[U_SHIELD].wIndex > 0) then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[U_SHIELD].wIndex);
    end;

    if (m_TorDDM.Tiger.DB.Dragon = 0) and ((StdItem = nil) or (not StdItem.Shape in [61..69])) then begin
      SysMsg('只有佩戴虎王盾才能放出虎王。', c_Red, t_Hint);
      Exit;
    end;

    if (m_TorDDM.Tiger.DB.Dragon > 0) and ((StdItem = nil) or (not StdItem.Shape in [70..72])) then begin
      SysMsg('只有佩戴龙王盾才能放出龙王。', c_Red, t_Hint);
      Exit;
    end;

    if (m_TorDDM.Tiger.DB.level <= 0) then begin
      SysMsg(Format('%s王等级小于1级,不能召出%s王。', [sName, sName]), c_Red, t_Hint);
      Exit;
    end;

    if (m_TorDDM.Tiger.Abil.MaxHP <= 0) then begin
      SysMsg(Format('%s王HP为0,不能召出%s王。', [sName, sName]), c_Red, t_Hint);
      Exit;
    end;

    dwNowWolTime := DateTimeToWolTIme(Now);
    case m_TorDDM.Tiger.DB.level of
      0..30: nReCallTime := 1200;
      31..50: nReCallTime := 900;
      51..80: nReCallTime := 600;
    else nReCallTime := 300;
    end;

    //重置虎灵值
    if (m_TorDDM.Tiger.DB.ReCallTick > dwNowWolTime) then m_TorDDM.Tiger.DB.ReCallTick := 0;

    if (dwNowWolTime < (m_TorDDM.Tiger.DB.ReCallTick + nReCallTime)) then begin
      SysMsg(Format('你当前的%s灵值未满,你还需等待%d秒才可释放出%s王。', [sName, (m_TorDDM.Tiger.DB.ReCallTick + nReCallTime - dwNowWolTime), sName]), c_Red, t_Hint);
      Exit;
    end;
    if (m_TorDDM.Tiger.DB.Dragon > 0) then begin
      if m_btJob in [0..2] then sName := sDragonName[m_btJob];
    end else
      sName := sTigerName;

    m_Tiger := TAnimalObject(MakeSlave(sName, m_TorDDM.Tiger.DB.level, m_TorDDM.Tiger.DB.level, 100, 24 * 60 * 60, -1));
    if m_Tiger <> nil then begin
      m_Tiger.m_btTigerDragon := m_TorDDM.Tiger.DB.Dragon + 1;
      if (m_TorDDM.Tiger.DB.Dragon > 0) then
        m_Tiger.m_btJob := m_btJob
      else
        m_Tiger.m_btJob := 0;
      RecalcTigerAbility;
      m_Tiger.m_WAbil.dwHP := m_Tiger.m_WAbil.dwMaxHP;
      m_Tiger.HealthSpellChanged();
      if m_UseItems[U_SHIELD].sExName <> '' then begin
        m_Tiger.m_sCharName := m_UseItems[U_SHIELD].sExName;
        m_Tiger.RefShowName;
      end;
      if m_TorDDM.Tiger.DB.Dragon > 0 then
        m_sScriptParam[0] := '1'
      else
        m_sScriptParam[0] := '0';
      ExecuteScript(g_FunctionNPC, '@ReleaseTiger');
    end;
    m_TorDDM.Tiger.DB.ReCallTick := dwNowWolTime;
    SendDefMessage(CM_CALLTIGER, dwNowWolTime, 1, 0, 0, '');
  end;
end;

//取消交易

procedure TPlayObject.ClientCancelDeal;
begin
  DealCancel();
end;

{玉净瓶俘获心魔}

procedure TPlayObject.ClientCatchEvil(EvilObject: TBaseObject; nMakeIndex:
  Integer);
var
  UserItem                              : pTUserItem;
begin
  if not m_boCanUseItem then Exit;
  if (not m_boDeath) and (not m_boGhost) then begin
    if m_PEnvir.IsValidObject(m_nCurrX, m_nCurrY, 1, EvilObject) then begin
      if (EvilObject.m_btRaceServer = RC_EVIL) and (EvilObject.m_btRaceImg in
        [0, 255]) and (EvilObject.m_boDeath) and (not EvilObject.m_boGhost) then begin
        GetUserItemByMakeIndex(nMakeIndex, UserItem);
        if UserItem = nil then Exit;
        if UserItem.Dura > 0 then begin
          if (UserItem.Evil.MakeIndex = 0) and (UserItem.Evil.sName = '') then begin
            m_sScriptParam[0] := IntToStr(UserItem.MakeIndex);
            m_sScriptParam[1] := IntToStr(EvilObject.m_btAmbitLevel);
            m_sScriptParam[2] := IntToStr(EvilObject.m_btJob);
            m_sScriptParam[3] := EvilObject.m_sFilterCharName;
            m_sScriptParam[4] := EvilObject.m_sCharName;
            m_sScriptParam[5] := IntToStr(Integer(EvilObject));
            ExecuteScript(g_FunctionNPC, '@封印心魔');
          end else
            SysMsg('玉净瓶的魔力有限,无法用来俘获第二个心魔', c_Pink, t_Hint);
        end else begin
          SendDelItems(UserItem);
          DelBagItem(UserItem.MakeIndex, UserEngine.GetStdItemName(UserItem.wIndex));
          SysMsg('玉净瓶已经破碎!!!', c_Red, t_Hint);
        end;
      end;
    end;
  end;
end;

//改变交易价格

procedure TPlayObject.ClientChangeDealGold(nGold, nGameGold: Integer);                              //004DDB04
var
  bo09                                  : Boolean;
begin
  //禁止取回放入交易栏内的金币
  if (nGold > 0) and (m_nDealGolds > 0) and g_Config.boCanNotGetBackDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sDealItemsDenyGetBackMsg);
    SendDefMessage(SM_DEALDELITEM_FAIL, 0, 0, 0, 0, '');
    Exit;
  end;
  if (nGameGold > 0) and (m_nDealGameGolds > 0) and g_Config.boCanNotGetBackDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sDealItemsDenyGetBackMsg);
    SendDefMessage(SM_DEALDELITEM_FAIL, 0, 0, 0, 1, '');
    Exit;
  end;
  //金币
  if (nGold < 0) then begin
    SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGolds, LoWord(m_nGold),
      HiWord(m_nGold), 0, '');
    Exit;
  end;
  //元宝
  if (nGameGold < 0) then begin
    SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGameGolds, LoWord(m_nGameGold),
      HiWord(m_nGameGold), 1, '');
    Exit;
  end;
  //检查交易金额,不能小于原来的金额
  if (nGold > 0) and (nGold < m_nDealGolds) then begin
    SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGolds, LoWord(m_nGold),
      HiWord(m_nGold), 0, '');
    Exit;
  end;
  if (nGameGold > 0) and (nGameGold < m_nDealGameGolds) then begin
    SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGameGolds, LoWord(m_nGameGold),
      HiWord(m_nGameGold), 1, '');
    Exit;
  end;

  //2013 金币大小不做检测了 Cloud
  //检查交易金额大小限制
//  if (nGameGold > 0) and (nGameGold > 2000) then begin
//    SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGameGolds, LoWord(m_nGameGold),
//      HiWord(m_nGameGold), 1, '');
//    Exit;
//  end;

  bo09 := False;
  if (m_DealCreat <> nil) {and (GetPoseCreate = m_DealCreat)} then begin
    if not m_DealCreat.m_boDealOK then begin
      if ((m_nGold + m_nDealGolds) >= nGold) and ((m_nGameGold +
        m_nDealGameGolds) >= nGameGold) then begin
        //改变当前交易的金额
        if nGold > 0 then begin
          IncGold(m_nDealGolds - nGold);
          m_nDealGolds := nGold;
        end;
        if nGameGold > 0 then begin
          m_nGameGold := (m_nGameGold + m_nDealGameGolds) - nGameGold;
          m_nDealGameGolds := nGameGold;
        end;
        //确认金币或元宝
        if nGold > 0 then begin
          SendDefMessage(SM_DEALCHGGOLD_OK, m_nDealGolds, LoWord(m_nGold),
            HiWord(m_nGold), 0, '');
          TPlayObject(m_DealCreat).SendDefMessage(SM_DEALREMOTECHGGOLD,
            m_nDealGolds, 0, 0, 0, '');
        end else begin
          SendDefMessage(SM_DEALCHGGOLD_OK, m_nDealGameGolds,
            LoWord(m_nGameGold), HiWord(m_nGameGold), 1, '');
          TPlayObject(m_DealCreat).SendDefMessage(SM_DEALREMOTECHGGOLD,
            m_nDealGameGolds, 0, 0, 1, '');
        end;
        m_DealCreat.m_DealLastTick := GetTickCount();
        bo09 := True;
        m_DealLastTick := GetTickCount();
      end;                                                                                          //004DDC50
    end;
  end;
  if not bo09 then begin
    if nGold > 0 then
      SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGolds, LoWord(m_nGold),
        HiWord(m_nGold), 0, '')
    else
      SendDefMessage(SM_DEALCHGGOLD_FAIL, m_nDealGameGolds, LoWord(m_nGameGold),
        HiWord(m_nGameGold), 1, '');
  end;
end;

//CM_TURN

function TPlayObject.ClientChangeDir(wIdent: word; nX, nY, nDir: Integer; var
  dwDelayTime: LongWord): Boolean;                                                                  //4CAEB8
var
  dwCheckTime                           : LongWord;
begin
  Result := False;
  if not CheckCanOperate(cRun) then Exit;

  if not CheckActionStatus(wIdent, dwDelayTime) then begin
    m_boFilterAction := False;
    Exit;
  end;
  m_boFilterAction := True;
  dwCheckTime := GetTickCount - m_dwTurnTick;
  if dwCheckTime < g_Config.dwTurnIntervalTime then begin
    dwDelayTime := g_Config.dwTurnIntervalTime - dwCheckTime;
    Exit;
  end;

  if (nX = m_nCurrX) and (nY = m_nCurrY) then begin
    m_btDirection := nDir;
    if Walk(RM_TURN) then begin
      m_dwTurnTick := GetTickCount();
      Result := True;
    end;
  end;
end;

//修改技能快捷键

procedure TPlayObject.ClientChangeMagicKey(nSkillIdx, nKey: Integer);                               //004DB9A4
var
  i                                     : Integer;
  UserMagic                             : pTUserMagic;
begin
  //不允许设置快捷键的技能
  if nSkillIdx in [SKILL_DRAGONROAR, SKILL_SWALLOWED, SKILL_RUSHTHUNDER,
   { SKILL_DRAGONPOWER, SKILL_DRAGONSHIELD, }SKILL_BLADEAREA..SKILL_127] then Exit;

  for i := 0 to m_MagicList.Count - 1 do begin
    UserMagic := m_MagicList.Items[i];
    if UserMagic.GetMagIdx = nSkillIdx then begin
      UserMagic.btKey := nKey;
      Break;
    end;
  end;
end;

//命令CM_CLICKNPC的处理

procedure TPlayObject.ClientClickNPC(NPC: Integer);                                                 //004DBA10
var
  NormNpc                               : TNormNpc;
  PlayObject                            : TBaseObject;
  i                                     : Integer;
  VisibleBaseObject                     : pTVisibleBaseObject;
  s                                     : string;
begin
  if m_boPneuma then Exit;                                                                          //元神不可以点击NPC

  if not m_boCanDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotTryDealMsg);
    Exit;
  end;
  if m_boDeath or m_boGhost then Exit;

  //发送活动日志
  if NPC = -5 then begin
    s := '';
    for i := 0 to UserEngine.m_Huodong.Count - 1 do
      s := s + UserEngine.m_Huodong[i];
    SendDefMessage(SM_MERCHANTSAY, Integer(g_FunctionNPC), 64, 0, 1, s);
    Exit;
  end;

  if m_ClickNPC = TObject(NPC) then
    NormNpc := TNormNpc(m_ClickNPC)
  else begin
    NormNpc := UserEngine.FindMerchant(TObject(NPC));
    if NormNpc = nil then
      NormNpc := UserEngine.FindNPC(TObject(NPC));
    m_ClickNPC := NormNpc;
  end;

  if NormNpc <> nil then begin                                                                      {摆摊时不允许点NPC}
    if ((m_wShopItemCount = 0) or NormNpc.m_boDoShop) and
      IsEnvir(NormNpc.m_PEnvir) and (abs(NormNpc.m_nCurrX - m_nCurrX) <= 15) and (abs(NormNpc.m_nCurrY - m_nCurrY) <= 15) then begin
      NormNpc.Click(Self);
    end;
  end else begin                                                                                    //2005/10/05增加:摆摊功能,当点击正在摆摊的玩家时,接收到的也是这个消息
    try
      PlayObject := nil;
      for i := 0 to m_VisibleActors.Count - 1 do begin
        VisibleBaseObject := m_VisibleActors.Items[i];
        if VisibleBaseObject.BaseObject = TObject(NPC) then begin
          PlayObject := TBaseObject(VisibleBaseObject.BaseObject);
          Break;
        end;
      end;
      if PlayObject <> nil then begin
        if (PlayObject = m_PackPet) or ((PlayObject.m_PEnvir = m_PEnvir) and
          (abs(PlayObject.m_nCurrX - m_nCurrX) <= 15) and
          (abs(PlayObject.m_nCurrY - m_nCurrY) <= 15)) then begin
          PlayObject.SendShopItems(Self, 1);
        end;
      end;
    except

    end;
  end;
end;

//创建队伍

procedure TPlayObject.ClientCreateGroup(sHumName: string);                                          //004DCCB4
var
  PlayObject                            : TPlayObject;
begin
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if m_GroupOwner <> nil then begin
    SendDefMessage(SM_CREATEGROUP_FAIL, -1, 0, 0, 0, '');
    Exit;
  end;
  if (PlayObject = nil) or (PlayObject = Self) or PlayObject.m_boDeath or
    PlayObject.m_boGhost then begin
    SendDefMessage(SM_CREATEGROUP_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;
  if (PlayObject.m_GroupOwner <> nil) then begin
    SendDefMessage(SM_CREATEGROUP_FAIL, -3, 0, 0, 0, '');
    Exit;
  end;
  if (PlayObject.m_boPneuma) then begin
    SendDefMessage(SM_CREATEGROUP_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;
  if (not PlayObject.m_boAllowGroup) then begin
    SendDefMessage(SM_CREATEGROUP_FAIL, -4, 0, 0, 0, '');
    Exit;
  end;
  if (PlayObject.m_PEnvir <> m_PEnvir) then begin                                                   //增加控制:必须在同一地图才可以组队
    SendDefMessage(SM_CREATEGROUP_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;

  FillChar(m_sGroupCommon, SizeOf(m_sGroupCommon), #0);                                             //清空队伍变量
  m_GroupMembers.Clear;
  m_GroupMembers.AddObject(m_sCharName, Self);
  m_GroupMembers.AddObject(sHumName, PlayObject);
  JoinGroup(Self);
  PlayObject.JoinGroup(Self);
  m_boAllowGroup := True;
  SendDefMessage(SM_CREATEGROUP_OK, 0, 0, 0, 0, '');
  SendGroupMembers();
end;

//创建第二元神

procedure TPlayObject.ClientCreateSoul(nParm1, nParm2, nParm3: Integer);
begin
  if m_boGhost or m_boDeath then Exit;
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnClientCreateSoul(Self, nParm1, nParm2, nParm3);
  except
    MainOutMessage(Format('TPlayObject::OnClientCreateSoul SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//交易完成

procedure TPlayObject.ClientDealEnd;
var
  i, j                                  : Integer;
  bo11                                  : Boolean;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  PlayObject                            : TPlayObject;
begin
  if m_DealCreat = nil then Exit;
  if ((GetTickCount - m_DealLastTick) < g_Config.dwDealOKTime {1000}) or
    ((GetTickCount - m_DealCreat.m_DealLastTick) < g_Config.dwDealOKTime {1000}) then begin
    SysMsg(g_sDealOKTooFast, c_Red, t_Hint);
    DealCancel();
    Exit;
  end;
  m_boDealOK := True;
  m_DealLastTick := GetTickCount;

  if m_DealCreat.m_boDealOK then begin
    bo11 := True;
    if (m_nBagSize - m_ItemList.Count) < m_DealCreat.m_DealItemList.Count then begin
      bo11 := False;                                                                                //包裹空间不足
      SysMsg(g_sYourBagSizeTooSmall, c_Red, t_Hint);
    end else if ((m_nGoldMax - m_nGold) < m_DealCreat.m_nDealGolds) then begin
      SysMsg(g_sYourGoldLargeThenLimit, c_Red, t_Hint);
      bo11 := False;                                                                                //金币超过限制
    end else if ((m_nGameGoldMax - m_nGameGold) < m_DealCreat.m_nDealGameGolds) then begin
      SysMsg(g_sYourGameGoldLargeThenLimit, c_Red, t_Hint);
      bo11 := False;                                                                                //元宝超过限制
    end else if (m_DealCreat.m_nBagSize - m_DealCreat.m_ItemList.Count) <
      m_DealItemList.Count then begin
      SysMsg(g_sDealHumanBagSizeTooSmall, c_Red, t_Hint);
      bo11 := False;                                                                                //包裹空间不足
    end else if ((m_DealCreat.m_nGoldMax - m_DealCreat.m_nGold) < m_nDealGolds) then begin
      SysMsg(g_sDealHumanGoldLargeThenLimit, c_Red, t_Hint);
      bo11 := False;                                                                                //金币超过限制
    end else if ((m_DealCreat.m_nGameGoldMax - m_DealCreat.m_nGameGold) <
      m_nDealGameGolds) then begin
      SysMsg(g_sDealHumanGameGoldLargeThenLimit, c_Red, t_Hint);
      bo11 := False;                                                                                //元宝超过限制
    end;

    if bo11 then begin
      for i := 0 to 27 do m_sDealParam[i] := '';                                                    //清空变量
      for i := 0 to m_DealItemList.Count - 1 do begin
        UserItem := m_DealItemList.Items[i];
        m_DealCreat.AddItemToBag(UserItem);
        TPlayObject(m_DealCreat).SendAddItem(UserItem);
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        m_sDealParam[i] := IntToStr(UserItem.MakeIndex);
        if StdItem <> nil then begin
          if not IsCheapStuff(StdItem.StdMode) then begin

            if StdItem.boGameLog = 1 then
              AddGameDataLog('8' + #9 +
                m_sMapName + #9 +
                IntToStr(m_nCurrX) + #9 +
                IntToStr(m_nCurrY) + #9 +
                m_sCharName + #9 +
                StdItem.Name + #9 +
                IntToStr(UserItem.MakeIndex) + #9 +
                '1' + #9 +
                m_DealCreat.m_sCharName);
          end;
        end;
      end;
      if m_nDealGolds > 0 then begin
        m_sDealParam[24] := IntToStr(m_nDealGolds);
        m_DealCreat.IncGold(m_nDealGolds);
        m_DealCreat.GoldChanged();
        if g_boGameLogGold then
          AddGameDataLog('14' + #9 +
            m_sMapName + #9 +
            IntToStr(m_nCurrX) + #9 +
            IntToStr(m_nCurrY) + #9 +
            m_sCharName + #9 +
            sSTRING_GOLDNAME + #9 +
            IntToStr(m_nGold) + #9 +
            '1' + #9 +
            m_DealCreat.m_sCharName);
      end;
      if m_nDealGameGolds > 0 then begin
        m_sDealParam[25] := IntToStr(m_nDealGolds);
        Inc(m_DealCreat.m_nGameGold, m_nDealGameGolds);
        m_DealCreat.GameGoldChanged();

        if g_boGameLogGameGold then
          AddGameDataLog('17' + #9 +
            m_sMapName + #9 +
            IntToStr(m_nCurrX) + #9 +
            IntToStr(m_nCurrY) + #9 +
            m_sCharName + #9 +
            sSTRING_GAMEGOLDNAME + #9 +
            IntToStr(m_nGameGold) + #9 +
            '2' + #9 +
            m_sCharName);
      end;

      for i := 0 to m_DealCreat.m_DealItemList.Count - 1 do begin
        UserItem := m_DealCreat.m_DealItemList.Items[i];
        AddItemToBag(UserItem);
        TPlayObject(Self).SendAddItem(UserItem);
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        m_sDealParam[12 + i] := IntToStr(UserItem.MakeIndex);
        if StdItem <> nil then begin
          if not IsCheapStuff(StdItem.StdMode) then begin

            if StdItem.boGameLog = 1 then
              AddGameDataLog('8' + #9 +
                m_DealCreat.m_sMapName + #9 +
                IntToStr(m_DealCreat.m_nCurrX) + #9 +
                IntToStr(m_DealCreat.m_nCurrY) + #9 +
                m_DealCreat.m_sCharName + #9 +
                StdItem.Name + #9 +
                IntToStr(UserItem.MakeIndex) + #9 +
                '1' + #9 +
                m_sCharName);
          end;
        end;
      end;
      if m_DealCreat.m_nDealGolds > 0 then begin
        m_sDealParam[26] := IntToStr(m_DealCreat.m_nDealGolds);
        IncGold(m_DealCreat.m_nDealGolds);
        GoldChanged();

        if g_boGameLogGold then
          AddGameDataLog('14' + #9 +
            m_DealCreat.m_sMapName + #9 +
            IntToStr(m_DealCreat.m_nCurrX) + #9 +
            IntToStr(m_DealCreat.m_nCurrY) + #9 +
            m_DealCreat.m_sCharName + #9 +
            sSTRING_GOLDNAME + #9 +
            IntToStr(m_DealCreat.m_nGold) + #9 +
            '1' + #9 +
            m_sCharName);
      end;

      if m_DealCreat.m_nDealGameGolds > 0 then begin
        m_sDealParam[27] := IntToStr(m_DealCreat.m_nDealGameGolds);
        Inc(m_nGameGold, m_DealCreat.m_nDealGameGolds);
        GameGoldChanged();

        if g_boGameLogGameGold then
          AddGameDataLog('17' + #9 +
            m_sMapName + #9 +
            IntToStr(m_nCurrX) + #9 +
            IntToStr(m_nCurrY) + #9 +
            m_sCharName + #9 +
            sSTRING_GAMEGOLDNAME + #9 +
            IntToStr(m_nGameGold) + #9 +
            '2' + #9 +
            m_DealCreat.m_sCharName);
      end;

      PlayObject := TPlayObject(m_DealCreat);


      m_sScriptParam[0] := PlayObject.m_sCharName;
      ExecuteScript(g_ManageNPC, '@_游戏_交易触发');


      PlayObject.SendDefMessage(SM_DEALSUCCESS, 0, 0, 0, 0, '');
      PlayObject.SysMsg(g_sDealSuccessMsg {'交易成功...'}, c_Green, t_Hint);
      PlayObject.m_DealCreat := nil;
      PlayObject.m_boDealing := False;
      PlayObject.m_DealItemList.Clear;
      PlayObject.m_nDealGolds := 0;
      PlayObject.m_nDealGameGolds := 0;
      PlayObject.m_boDealOK := False;
      UserEngine.SaveHumanRcd(Self);
      UserEngine.SaveHumanRcd(TPlayObject(m_DealCreat));
      m_dwSaveRcdTick := GetTickCount;
      TPlayObject(m_DealCreat).m_dwSaveRcdTick := GetTickCount;

      SendDefMessage(SM_DEALSUCCESS, 0, 0, 0, 0, '');
      SysMsg(g_sDealSuccessMsg {'交易成功...'}, c_Green, t_Hint);
      m_DealCreat := nil;
      m_boDealing := False;
      m_DealItemList.Clear;
      m_nDealGolds := 0;
      m_nDealGameGolds := 0;
      m_boDealOK := False;
    end else begin
      DealCancel();
    end;
  end else begin
    SysMsg(g_sYouDealOKMsg {'你已经确认交易了'}, c_Green, t_Hint);
    m_DealCreat.SysMsg(g_sPoseDealOKMsg {'对方已经确认交易了'},
      c_Green, t_Hint);
  end;
end;

//尝试交易

procedure TPlayObject.ClientDealTry(sHumName: string);
var
  BaseObject                            : TBaseObject;
begin
  if g_Config.boDisableDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sDisableDealItemsMsg);
    Exit;
  end;
  if m_boDealing then Exit;

  if GetTickCount - m_DealLastTick < g_Config.dwTryDealTime {3000} then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sPleaseTryDealLaterMsg);
    Exit;
  end;

  //摆摊状态下不允许交易。
  if not m_boCanDeal or (m_wShopItemCount > 0) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sCanotTryDealMsg);
    Exit;
  end;

  if m_boPneuma then begin
    SysMsg('元神分身也想玩交易?没门!', c_Red, t_Hint);
    Exit;
  end;

  //非和平攻击模式下不允许交易。
  if (m_btAttatckMode <> HAM_PEACE) then begin
    SysMsg(g_sCanotTryDealMsg2, c_Red, t_Hint);
    Exit;
  end;

  if m_boArrow then begin
    SysMsg('现在不能交易', c_Green, t_Hint);
    Exit;
  end;

  BaseObject := GetPoseCreate();

  if BaseObject = nil then BaseObject := UserEngine.GetPlayObject(sHumName);

  if (BaseObject <> nil) and (BaseObject <> Self) then begin
    if (not BaseObject.m_boDealing) then begin
      if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
        //检查对方是否元神
        if BaseObject.m_boPneuma then begin
          SysMsg('不可以和元神分身交易', c_Red, t_Hint);
          Exit;
        end;

        //检查对方是否是和平攻击模式
        if (BaseObject.m_btAttatckMode <> HAM_PEACE) then begin
          SysMsg(g_sCanotTryDealMsg3, c_Red, t_Hint);
          Exit;
        end;

        if BaseObject.m_boArrow then begin
          SysMsg('对方现在不能交易', c_Green, t_Hint);
          Exit;
        end;

        if (BaseObject.m_boAllowDeal and TPlayObject(BaseObject).m_boCanDeal) then begin
          BaseObject.SysMsg(m_sCharName + g_sOpenedDealMsg, c_Green, t_Hint);
          SysMsg(BaseObject.m_sCharName + g_sOpenedDealMsg, c_Green, t_Hint);
          TPlayObject(Self).OpenDealDlg(BaseObject);
          TPlayObject(BaseObject).OpenDealDlg(Self);
        end else begin                                                                              //004DD1CC
          SysMsg(g_sPoseDisableDealMsg {'对方禁止进入交易'}, c_Red, t_Hint);
        end;
      end;
    end else begin                                                                                  //004DD1E0
      SendDefMessage(SM_DEALTRY_FAIL, 0, 0, 0, 0, '');
    end;
  end else begin                                                                                    //004DD1F9
    SendDefMessage(SM_DEALTRY_FAIL, 0, 0, 0, 0, '');
  end;
end;

//删除要交易的物品

procedure TPlayObject.ClientDelDealItem(nItemIdx: Integer; sItemName: string);
var
  i                                     : Integer;
  bo11                                  : Boolean;
  UserItem                              : pTUserItem;
  sName                                 : string;
begin
  //如果不允许取回物品,则失败
  if g_Config.boCanNotGetBackDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sDealItemsDenyGetBackMsg);
    SendDefMessage(SM_DEALDELITEM_FAIL, 0, 0, 0, 0, '');
    Exit;
  end;

  if (m_DealCreat = nil) or (not m_boDealing) then Exit;

  bo11 := False;
  if not m_DealCreat.m_boDealOK then begin
    for i := m_DealItemList.Count - 1 downto 0 do begin
      UserItem := m_DealItemList.Items[i];
      if UserItem.MakeIndex = nItemIdx then begin

        //取自定义物品名称
        sName := '';
        ItemUnit.GetCustomItemName(UserItem, sName);

        if (CompareText(sItemName, sName) = 0) then begin
          m_ItemList.Add(UserItem);
          TPlayObject(Self).SendDelDealItem(UserItem);
          m_DealItemList.Delete(i);
          bo11 := True;
          Break;
        end;
      end;
    end;
  end;
  if not bo11 then
    SendDefMessage(SM_DEALDELITEM_FAIL, 0, 0, 0, 0, '');
end;

//删除好友

procedure TPlayObject.ClientDelFriend(FriendName: string);
var
  i                                     : Integer;
  human                                 : TPlayObject;
begin
  //检查要删除的人是否在我的好友名单中
  DelFromFriendList(FriendName);
  //对方从名单中删除我
  human := UserEngine.GetPlayObject(FriendName);
  if (human <> nil) and (not human.m_boDeath) and (not human.m_boGhost) then begin
    human.DelFromFriendList(m_sCharName);
  end else begin                                                                                    //不在线,则自己来删除对方的好友

  end;
  m_sScriptParam[0] := FriendName;
  ExecuteScript(g_ManageNPC, '@人脉_删除好友');
end;

//删除队伍成员

procedure TPlayObject.ClientDelGroupMember(sHumName: string);                                       //004DCFB8
var
  PlayObject                            : TPlayObject;
begin
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if m_GroupOwner <> Self then begin
    SendDefMessage(SM_GROUPDELMEM_FAIL, -1, 0, 0, 0, '');
    Exit;
  end;
  if PlayObject = nil then begin
    SendDefMessage(SM_GROUPDELMEM_FAIL, -2, 0, 0, 0, '');
    Exit;
  end;
  if not IsGroupMember(PlayObject) then begin
    SendDefMessage(SM_GROUPDELMEM_FAIL, -3, 0, 0, 0, '');
    Exit;
  end;
  DelMember(PlayObject);
  SendDefMessage(SM_GROUPDELMEM_OK, 0, 0, 0, 0, sHumName);

  PlayObject.ExecuteScript(g_FunctionNPC, '@_退出队伍');
end;

//摆摊

procedure TPlayObject.ClientDoShop(shopItemCount: word; sMsg: string);
var
  RetCode                               : Integer;
  DoShopResult                          : TDoShopResult;
  i, j, ii                              : Integer;
  UserShop                              : TUserShop;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  boFind                                : Boolean;
  sName                                 : string;
  Castle                                : TUserCastle;
  BaseObjectList                        : TList;
  BaseObject                            : TBaseObject;
resourcestring
  sHint1                                = '骑宠状态不能摆摊。';
  sHint2                                = '此地图禁止摆摊。';
  sHint3                                = '正在攻城的区域禁止摆摊。';
  sHint4                                = '你正在进行抢宝活动,禁止摆摊。';
  sHint5                                = '周围没有空的位置,无法摆下你的摊位。';
  sHint6                                = '摆摊物品价格定义错误,请勿使用非法外挂!';
  sHint7                                = '金币交易价格定义超过允许的范围。';
  sHint8                                = '元宝交易价格定义超过允许的范围。';
  sHint9                                = '此物品开启后不允许交易,但时间到后可丢弃。';
  sHint10                               = '你要出售的物品并不存在。';
  sHint11                               = ' 不允许交易。';
begin
  if not m_boCanDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotTryDealMsg);
    Exit;
  end;

  if m_boRideOn then begin
    SysMsg(sHint1, c_Red, t_Hint);
    Exit;
  end;

  if m_PEnvir.m_MapFlag.boNoDoShop then begin
    SysMsg(sHint2, c_Red, t_Hint);
    Exit;
  end;

  Castle := g_CastleManager.InCastleWarArea(Self);
  //城堡正在战斗
  if (Castle <> nil) and Castle.m_boUnderWar then begin
    SysMsg(sHint3, c_Red, t_Hint);
    Exit;
  end;

  if m_boArrow then begin
    SysMsg(sHint4, c_Red, t_Hint);
    Exit;
  end;

  BaseObjectList := TList.Create;
  try
    GetMapBaseObjects(m_PEnvir, m_nCurrX, m_nCurrY, 2, BaseObjectList);
    for i := 0 to BaseObjectList.Count - 1 do begin
      BaseObject := TBaseObject(BaseObjectList.Items[i]);
      if (BaseObject.m_btRaceServer = RC_NPC) then begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你离NPC太近了,不能摆摊。');
        Exit;
      end;
    end;
  finally
    BaseObjectList.free;
  end;

  //检查前后左右有没有空位置
  if (m_wShopItemCount = 0) and (shopItemCount > 0) then begin                                      //开始摆摊的时候才需要判断
    if (m_nCurrX > 0) and (m_nCurrX < m_PEnvir.m_nWidth) and
      (m_nCurrY > 0) and (m_nCurrY < m_PEnvir.m_nHeight) and
      m_PEnvir.CanWalk(m_nCurrX, m_nCurrY - 1, True) and
      m_PEnvir.CanWalk(m_nCurrX + 1, m_nCurrY - 1, True) and
      m_PEnvir.CanWalk(m_nCurrX + 1, m_nCurrY, True) and
      m_PEnvir.CanWalk(m_nCurrX + 1, m_nCurrY + 1, True) and
      m_PEnvir.CanWalk(m_nCurrX, m_nCurrY + 1, True) and
      m_PEnvir.CanWalk(m_nCurrX - 1, m_nCurrY + 1, True) and
      m_PEnvir.CanWalk(m_nCurrX - 1, m_nCurrY, True) and
      m_PEnvir.CanWalk(m_nCurrX - 1, m_nCurrY - 1, True) then
    else begin
      SysMsg(sHint5, c_Red, t_Hint);
      Exit;
    end;
  end;

  m_wShopItemCount := _MIN(15, shopItemCount);
  if m_wShopItemCount = 0 then begin
    RetCode := $FF;
  end else begin                                                                                    //判断能否摆摊
    RetCode := 0;
  end;

  FillChar(m_Shop, SizeOf(TShop), #0);
  if (RetCode = 0) and (m_wShopItemCount > 0) and (sMsg <> '') then begin                           //取摊位名字和物品
    DeCodeBuffer(sMsg, @m_Shop, SizeOf(TShop));
  end;
  //检测摊位名称
  if CheckFilterWords(m_Shop.ShopName) or AnsiContainsText(m_Shop.ShopName, '\') then begin
    m_wShopItemCount := 0;
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '输入内容含有非法字符!');
    Exit;
  end;
  for i := 0 to m_wShopItemCount - 1 do begin
    if m_Shop.ShopItems[i].MakeIndex <> 0 then begin
      if not (m_Shop.ShopItems[i].PayType in [0..1]) then begin
        SysMsg(sHint6, c_Red, t_Hint);
        m_wShopItemCount := 0;
        Exit;
      end;                                                                                          //150 000 000 //2000
      if (m_Shop.ShopItems[i].PayType = 0) and ((m_Shop.ShopItems[i].Price < 1)
        or (m_Shop.ShopItems[i].Price > 150000000)) then begin
        SysMsg(sHint7, c_Red, t_Hint);
        m_wShopItemCount := 0;
        Exit;
      end;
      if (m_Shop.ShopItems[i].PayType = 1) and ((m_Shop.ShopItems[i].Price < 1)
        or (m_Shop.ShopItems[i].Price > 10000000)) then begin
        SysMsg(sHint8, c_Red, t_Hint);
        m_wShopItemCount := 0;
        Exit;
      end;

      //检查物品合法性
      boFind := False;
      for j := 0 to m_ItemList.Count - 1 do begin
        UserItem := pTUserItem(m_ItemList[j]);
        if UserItem.MakeIndex = m_Shop.ShopItems[i].MakeIndex then begin
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if StdItem = nil then Break;

          sName := '';
          ItemUnit.GetCustomItemName(UserItem, sName);

          {物品控制-禁止摆摊物品}
          if CheckSPCode(StdItem.SPCode, SP_DISABLEDOSHOP) or
            ((UserItem.btItemExt[4] and EX_BIND) = EX_BIND) then begin
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sName + sHint11);
            m_wShopItemCount := 0;
            Exit;
          end;

          {魂佑灵兽禁止交易}
          if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '魂佑灵兽禁止交易');
            m_wShopItemCount := 0;
            Exit;
          end;

          {已放出宠物禁止出售}
          if IsDownPetItem(UserItem.MakeIndex) then begin
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sName + sHint11);
            m_wShopItemCount := 0;
            Exit;
          end;

          boFind := True;
          Break;
        end;
      end;
      if not boFind then begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sHint10);
        m_wShopItemCount := 0;
        Exit;
      end;
    end;
  end;

  for i := m_wShopItemCount to 14 do begin
    m_Shop.ShopItems[i].MakeIndex := 0;
    m_Shop.ShopItems[i].Price := 0;
    m_Shop.ShopItems[i].PayType := 0;
  end;

  DoShopResult.ShopType := m_wShopKind;
  DoShopResult.RetCode := RetCode;
  DoShopResult.FlagType := m_btShopBanner;
  DoShopResult.FlagColor := m_nBannerColor;
  if (RetCode = 0) and ((m_btDirection mod 2) = 0) then
    m_btDirection := m_btDirection + 1;
  m_defMsg := MakeDefaultMsg(SM_DOSHOP, Integer(Self), m_nCurrX, m_nCurrY,
    m_btDirection);
  SendSocket(@m_defMsg, EnCodeBuffer(@DoShopResult, SizeOf(TDoShopResult)));

  UserShop.DoShopResult.ShopType := m_wShopKind;
  UserShop.DoShopResult.RetCode := RetCode;
  UserShop.DoShopResult.FlagType := m_btShopBanner;
  UserShop.DoShopResult.FlagColor := m_nBannerColor;
  UserShop.GoodsCount := 0;
  UserShop.ShopName := m_Shop.ShopName;

  //发送操作结果和商店名称
  SendRefMsg(RM_DOSHOP, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), RetCode, 0,
    EnCodeBuffer(@UserShop, 62));

  if (not m_boPneuma) then begin
    m_sScriptParam[0] := '0';
    ExecuteScript(g_FunctionNPC, '@开始摆摊');
  end;
end;

function TPlayObject.ClientDropGold(nGold: Integer): Boolean;                                       //004C5BB0
begin
  Result := False;
  //安全区是否允许扔金币
  if g_Config.boInSafeDisableDrop and InSafeZone then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sCanotDropInSafeZoneMsg);
    Exit;
  end;

  //扔金币数量的控制
  if g_Config.boControlDropItem and (nGold < g_Config.nCanDropGold) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sCanotDropGoldMsg);
    Exit;
  end;

  //本人物是否允许扔金币
  if not m_boCanDrop or (m_wShopItemCount > 0) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
      g_sCanotDropItemMsg);
    Exit;
  end;
  //扔的金币数是否大于已有金币数
  if nGold > m_nGold then Exit;

  DecGold(nGold);
  if not DropGoldDown(nGold, False, nil, Self) then IncGold(nGold);
  GoldChanged();

  if g_Config.boStartMapEvent then begin
    StartMapEventOfDropItem(sSTRING_BINDGOLDNAME);
  end;
  Result := True;
end;

//检测是否放出的宠物

function TPlayObject.IsDownPetItem(nMakeIndex: Integer): Boolean;
var
  i                                     : Integer;
begin
  Result := False;
  for i := 0 to 5 do begin
    if nMakeIndex = m_PetInfo[i].nMakeIndex then begin
      Result := True;
      Break;
    end;
  end;
end;

//扔其他物品

function TPlayObject.ClientDropItem(sItemName: string; nItemIdx: Integer): Boolean;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ClientDropItem Code=%d';
var
  i, ii                                 : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  sName                                 : string;
  FireBurnEff                           : word;                                                     //烟花效果
  nCheckCode                            : Integer;
begin
  Result := False;
  nCheckCode := 0;
  FireBurnEff := 0;
  try
    if (GetTickCount - m_DealLastTick) > 3000 then begin
      nCheckCode := 1;
      for i := m_ItemList.Count - 1 downto 0 do begin
        UserItem := m_ItemList.Items[i];
        if (UserItem <> nil) and (UserItem.MakeIndex = nItemIdx) then begin
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if StdItem = nil then Continue;
          nCheckCode := 2;

          sName := '';
          ItemUnit.GetCustomItemName(UserItem, sName);

          nCheckCode := 3;
          if (CompareText(sItemName, sName) = 0) then begin
            //烟花
            nCheckCode := 4;
            if (StdItem.StdMode = 52) then
              FireBurnEff := MakeWord(StdItem.Shape, StdItem.AniCount);
            nCheckCode := 5;
            //兽粮
            if (StdItem.StdMode = 49) and (StdItem.Shape = 52) then begin
              nCheckCode := 6;
              if (m_Pet <> nil) and (abs(m_nCurrX - m_Pet.m_nCurrX) <= 2) and (abs(m_nCurrY - m_Pet.m_nCurrY) <= 2) then begin
                nCheckCode := 7;
                if PetStoreAddExp(m_PetInfo[0].nMakeIndex, StdItem.DuraMax, LoWord(StdItem.AC), False) then begin
                  nCheckCode := 8;
                  Dispose(UserItem);
                  m_ItemList.Delete(i);
                  Result := True;
                  m_Pet.SendRefMsg(RM_HIT, m_Pet.m_btDirection, m_Pet.m_nCurrX, m_Pet.m_nCurrY, 0, '');
                  Break;
                end;
                nCheckCode := 9;
              end else begin
                SysMsg('你的身边没有可喂食的宠物,不能喂食。', c_Red, t_Hint);
                Break;
              end;
            end;
            nCheckCode := 10;
            //烟花类
            if FireBurnEff > 0 then begin
              nCheckCode := 11;
              SendRefMsg(RM_FIREBURN, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), 0, 0, EnCodeBuffer(@FireBurnEff, SizeOf(word)));
              nCheckCode := 12;
              Dispose(UserItem);
              m_ItemList.Delete(i);
              Result := True;
              Break;
            end;
            nCheckCode := 13;
            //安全区是否允许扔物品
            if g_Config.boInSafeDisableDrop and InSafeZone then begin
              if g_Config.boShowScriptActionMsg then
                SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotDropInSafeZoneMsg)
              else
                SysMsg(g_sCanotDropInSafeZoneMsg, c_Pink, t_Hint);
              Break;
            end;
            nCheckCode := 14;
            //本人物是否允许扔物品
            if not m_boCanDrop then begin
              SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotDropItemMsg);
              Break;
            end;
            nCheckCode := 15;
            //物品控制-禁止丢弃
            if CheckSPCode(StdItem.SPCode, SP_DISABLEDROP) or
              ((UserItem.btItemExt[4] and EX_BIND) = EX_BIND) then begin
              Break;
            end;

            {魂佑灵兽禁止丢弃}
            if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
              SysMsg('魂佑灵兽石不允许丢弃!', c_Red, t_Hint);
              Break;
            end;

            {已放出豹禁止丢弃}
            if IsDownPetItem(UserItem.MakeIndex) then begin
              SysMsg('已经放出灵兽的' + sName + '不能丢弃!', c_Red, t_Hint);
              Break;
            end;

            nCheckCode := 16;
            if g_Config.boControlDropItem and (StdItem.Price < g_Config.nCanDropPrice) then begin
              Dispose(UserItem);
              m_ItemList.Delete(i);
              Result := True;
              Break;
            end;
            nCheckCode := 17;
            if DropItemDown(UserItem, 3, False, nil, Self) then begin
              Dispose(UserItem);
              m_ItemList.Delete(i);
              Result := True;
              Break;
            end;
          end;
        end;
      end;
      nCheckCode := 18;
      if Result then begin
        WeightChanged();
        //丢物品触发脚本
        if (m_btRaceServer = RC_PLAYOBJECT) and (g_FunctionNPC <> nil) and (not m_boPneuma) then begin
          ExecuteScript(g_FunctionNPC, '@DropItem' + IntToStr(StdItem.AniCount));
        end;
        nCheckCode := 19;
        if g_Config.boStartMapEvent then begin
          StartMapEventOfDropItem(StdItem.Name);
        end;
      end;
    end;
  except
    MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
  end;
end;

procedure TPlayObject.ClientEnlargeTreasureBox();
begin
  if (m_TreasureBoxItem = nil) or (m_TreasureBoxItem.DuraMax >= 20) then Exit;
  if (m_Abil.wNimBusPoint < 10) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你的灵力不足10点,无法扩充灵犀宝盒');
    Exit;
  end;
  Dec(m_Abil.wNimBusPoint, 10);
  RecalcAbilitys();
  SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  m_TreasureBoxItem.DuraMax := m_TreasureBoxItem.DuraMax + 2;
  ClientQueryTreasureBoxItems(False);
  SendDefMessage(SM_INFORMATION, 0, 0, 0, 0,
    Format('你的灵犀宝盒格子扩充成功,您现在拥有<color=green %d>个格子', [m_TreasureBoxItem.DuraMax]));
end;

{神龙献宝}

procedure TPlayObject.ClientErnie(nOpCode: word);
var
  nLineCount                            : Integer;
  NPC                                   : TNormNpc;
begin
  if m_boGhost or m_boDeath then Exit;
  case LoByte(nOpCode) of
    0: begin                                                                                        //宝石类停止

      end;
    1: begin                                                                                        //宝石类开始

      end;
    2: begin

      end;
    3: begin                                                                                        //弹出摇奖机,神龙在此刻觉醒
        //sGiftName := '强化火球四重';
        //SendDefMessage(34972, 0, 1, 0, 0, '今日神龙宝藏:' + sGiftName);
      end;
    4: begin                                                                                        //神龙献宝开始
        nLineCount := HiByte(nOpCode);
        NPC := UserEngine.FindMerchant(m_SMELTNPC);
        if (NPC = nil) then
          NPC := UserEngine.FindNPC(m_SMELTNPC);
        if (NPC <> nil) then begin
          m_sScriptParam[0] := IntToStr(nLineCount);
          NPC.GotoLable(Self, '@StartErnie', False);
        end;
      end;
    5: begin                                                                                        //神龙献宝停下
        if (m_nRandomGiveStep = 1) then begin
          m_nRandomGiveStep := 0;
          NPC := UserEngine.FindMerchant(m_SMELTNPC);
          if (NPC = nil) then
            NPC := UserEngine.FindNPC(m_SMELTNPC);
          if (NPC <> nil) then begin
            NPC.GotoLable(Self, '@EndErnie', False);
          end;
        end;
      end;
  end;
end;

{心魔控制}

procedure TPlayObject.ClientEvilOp(nOpCode: Integer; nEvilMonID: Integer;
  nMakeIndex: Integer);
var
  i, nCount                             : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  mon, BaseObject                       : TBaseObject;
begin
  mon := nil;
  for i := 0 to m_SlaveList.Count - 1 do begin
    if TBaseObject(m_SlaveList[i]).m_btRaceServer = RC_EVIL then begin
      mon := TBaseObject(m_SlaveList[i]);
      Break;
    end;
  end;
  if mon = nil then Exit;

  {检查物品}
  if nMakeIndex > 0 then begin
    GetUserItemByMakeIndex(nMakeIndex, UserItem);
    if (UserItem <> nil) then
      StdItem := UserEngine.GetStdItem(UserItem.wIndex)
    else
      StdItem := nil;
    if (UserItem = nil) or (StdItem = nil) then Exit;
  end;

  case nOpCode of
    4: begin                                                                                        //心魔绝杀
        if (m_wStatusTimeArr[POISON_DONTMOVE] > 0) or
          ((m_wStatusTimeArr[POISON_STONE] > 0) and not g_Config.ClientConf.boParalyCanHit) then Exit; //被麻痹不能使用
        if (GetTickCount - m_dwEvilUniQueSkillTick) < 10 * 1000 then begin
          SysMsg('你控制的心魔已经处在强力攻击状态!', c_Red, t_Hint);
          Exit;
        end;
        if m_nEvilFollowerPower < g_Config.nEvilUniQueSkillDecPower * 1000 then begin
          SysMsg('镇魔力不足,无法发动强力攻击!', c_Red, t_Hint);
          Exit;
        end;
        if (GetTickCount - m_dwEvilUniQueSkillTick) <
          g_Config.nUseEvilUniQueSkillTick * 1000 then begin
          SysMsg('心魔绝杀技需间隔' +
            IntToStr(g_Config.nUseEvilUniQueSkillTick) + '秒才能使用一次', c_Red, t_Hint);
          Exit;
        end;
        for i := 0 to m_VisibleActors.Count - 1 do begin
          BaseObject :=
            TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
          if BaseObject.m_boDeath or BaseObject.m_boGhost then Continue;
          if (abs(m_nCurrX - BaseObject.m_nCurrX) < 15) and (abs(m_nCurrY -
            BaseObject.m_nCurrY) < 15) then begin
            if IsProperTarget(BaseObject) then begin
              BaseObject.MakePosion(POISON_DONTMOVE, g_Config.nEvilUniQueSkillDontMoveTime, 0);
              BaseObject.SetLastHiter(Self);
            end;
          end;
        end;
        {心魔绝杀}
        ClearEvilFollower(0);
        m_dwEvilUniQueSkillTick := GetTickCount;
        Dec(m_nEvilFollowerPower, g_Config.nEvilUniQueSkillDecPower * 1000);
        SendDefMessage(CM_RECALLEVIL, Integer(Self), 260,
          LoWord(m_nEvilFollowerPower), HiWord(m_nEvilFollowerPower), '');
      end;
    5: begin                                                                                        //点面板上的“镇”字,有物品ID无心魔ID
        if m_nEvilFollowerPower >= m_nEvilFollowerPowerMax then begin                               //镇魔力量已经很强了,无需再增加
          SysMsg('镇魔力量已经很强了,无需再增加', c_Red, t_Hint);
          Exit;
        end;
        m_nEvilFollowerPower := _MIN(m_nEvilFollowerPowerMax,
          m_nEvilFollowerPower + StdItem.AC * 1000);
        if UserItem.Dura <= 1 then begin
          SendDelItems(UserItem);
          DelBagItem(UserItem.MakeIndex, StdItem.Name);
          WeightChanged;
        end else begin
          Dec(UserItem.Dura);
          SendUpdateItem(UserItem);
        end;
        SendDefMessage(34968, Integer(Self), 3, LoWord(m_nEvilFollowerPower),
          HiWord(m_nEvilFollowerPower), '');
        ClearEvilFollower(4);
      end;
    6: begin                                                                                        //解除,就是释放这个心魔宝宝
        nCount := 0;
        for i := m_SlaveList.Count - 1 downto 0 do begin
          if TBaseObject(m_SlaveList[i]).m_btRaceServer = RC_EVIL then begin
            Inc(nCount);
            if nEvilMonID = Integer(m_SlaveList[i]) then begin
              SysMsg(Format('你的宠物(%s)叛变了', [TBaseObject(m_SlaveList[i]).m_sFilterCharName]), c_Pink, t_Hint);
              TBaseObject(m_SlaveList[i]).m_Master := nil;
              TBaseObject(m_SlaveList[i]).m_boSuperMan := False;
              TBaseObject(m_SlaveList[i]).m_btNameColor := $F9;
              TBaseObject(m_SlaveList[i]).RefNameColor;
              TBaseObject(m_SlaveList[i]).RefShowName;
              TBaseObject(m_SlaveList[i]).HealthSpellChanged;
              m_SlaveList.Delete(i);
              Dec(nCount);
            end;
          end;
        end;
        if nCount = 0 then begin
          SendDefMessage(CM_RECALLEVIL, 0, 1, 0, 0, '');
          m_nEvilFollowerPower := 0;
        end;
        SendDefMessage(34968, Integer(Self), 3, LoWord(m_nEvilFollowerPower),
          HiWord(m_nEvilFollowerPower), '');
        ClientQueryEvilFollower();
      end;
  end;
end;

procedure TPlayObject.ClientEvoluTion(wParam: word; nMainMakeIndex,
  nAuxMakeIndex, nMakeIndex: Integer);
var
  UserItem                              : pTUserItem;
begin
  if (not m_boDeath) and (not m_boGhost) and (not m_boPneuma) then begin
    if (GetUserItemByMakeIndex(nMainMakeIndex, UserItem) < 0) or
      (GetUserItemByMakeIndex(nAuxMakeIndex, UserItem) < 0) then Exit;
    if (nMakeIndex > 0) and (GetUserItemByMakeIndex(nMakeIndex, UserItem) < 0) then nMakeIndex := 0;
    if nMakeIndex < 0 then nMakeIndex := 0;
    m_sScriptParam[0] := IntToStr(wParam);                                                          //封元印
    m_sScriptParam[1] := IntToStr(nMainMakeIndex);                                                  //主灵兽
    m_sScriptParam[2] := IntToStr(nAuxMakeIndex);                                                   //副灵兽
    m_sScriptParam[3] := IntToStr(nMakeIndex);
    ExecuteScript(g_FunctionNPC, '@灵兽幻化');
  end;
end;

//灵兽繁衍

procedure TPlayObject.ClientPetMakeBaby(nMaleMakeIndex, nFemaleMakeIndex: Integer);
var
  UserItem                              : pTUserItem;
begin
  if (not m_boDeath) and (not m_boGhost) and (not m_boPneuma) then begin
    if (GetUserItemByMakeIndex(nMaleMakeIndex, UserItem) < 0) or (GetUserItemByMakeIndex(nFemaleMakeIndex, UserItem) < 0) then Exit;

    m_sScriptParam[0] := IntToStr(nMaleMakeIndex);                                                  //雄灵兽
    m_sScriptParam[1] := IntToStr(nFemaleMakeIndex);                                                //雌灵兽
    ExecuteScript(g_FunctionNPC, '@繁衍灵兽');
  end;
end;

//五行令旗

procedure TPlayObject.ClientFelementOrderFlag(nMakeIndex, nMon: Integer);
var
  i                                     : Integer;
  mon                                   : TBaseObject;
  Targe                                 : TBaseObject;
  UserItem                              : pTUserItem;
  boEatOK                               : Boolean;
begin
  boEatOK := False;
  Targe := nil;
  if GetUserItemByMakeIndex(nMakeIndex, UserItem) > -1 then begin
    if nMon > 0 then Targe := TBaseObject(nMon);
    if (nMon > 0) and (Targe <> nil) and (not Targe.m_boDeath) and
      (not Targe.m_boGhost) and (Targe.m_btRaceServer = RC_MISSION) and
      (Targe.m_boMission) then begin
      if UserItem.Dura > 0 then Dec(UserItem.Dura);
      if (UserItem.Dura <= 0) then begin
        DelBagItem(nMakeIndex, '');
        boEatOK := True;
      end else begin
        SendUpdateItem(UserItem);
      end;
      //指定攻击目标
      for i := 0 to m_SlaveList.Count - 1 do begin
        mon := m_SlaveList[i];
        if not (mon.m_btRaceServer in [14, 21]) then Continue;
        mon.m_FirstTargetCret := Targe;
        mon.SetTargetCreat(Targe);
      end;
      SendDefMessage(3046, m_btDirection, LoWord(nMon), HiWord(nMon), 1, '');
      SysMsg(Format('使用五行令旗成功,将<%s>指定为首要攻击目标!', [Targe.m_sFilterCharName]), c_Red, t_Hint);
    end;
  end;
  if not boEatOK then SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
end;

procedure TPlayObject.ClientGemItems(NPC: Integer; nType: Integer; nItemCount:
  Integer; nState: Integer; sData: string);
var
  buf                                   : array[0..9] of Integer;
  i, j                                  : Integer;
  nCode, nRate                          : Integer;
  ANpc                                  : TNormNpc;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  GemItems                              : array[0..9] of pTUserItem;
  GemStdItems                           : array[0..9] of pTStdItem;
  sMsg, sLable, DestItemName            : string;
  sLableOK                              : string;
begin
  for i := 0 to 9 do begin
    m_sScriptParam[i] := '';
    GemItems[i] := nil;
    GemStdItems[i] := nil;
  end;
  sLable := '';
  sLableOK := '';
  FillChar(buf, SizeOf(buf), #0);
  DeCodeBuffer(sData, @buf, SizeOf(Integer) * nItemCount);

  if m_btPermissionGM > 6 then begin
    SysMsg(Format('当前指令编号为:%d', [nType]), c_Red, t_Hint);
    SysMsg(Format('当前指令状态为:%d', [nState]), c_Red, t_Hint);
    SysMsg(Format('当前NPC编号为:%d', [NPC]), c_Blue, t_Hint);
  end;

  if nType in [2, 5] then begin
    if NPC = Integer(Self) then
      ANpc := TNormNpc(m_SMELTNPC)
    else
      ANpc := UserEngine.FindMerchant(TObject(NPC));
  end else begin
    ANpc := UserEngine.FindMerchant(TObject(NPC));
  end;
  if ANpc = nil then ANpc := UserEngine.FindNPC(TObject(NPC));

  if ANpc = nil then Exit;

  {函数入口初始}
  nCode := 0;
  for i := 0 to nItemCount - 1 do begin
    GemItems[i] := nil;
    for j := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[j];
      if UserItem.MakeIndex = buf[i] then begin
        GemItems[i] := UserItem;
        GemStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
        Break;
      end;
    end;
  end;

  {函数标签初始}
  case nType of
    0: sLable := '@@gemcondense';                                                                   //宝石凝练
    1: sLable := '@@gemcompound';                                                                   //宝石合成
    2: sLable := '@@weaponcompound';                                                                //武器铸造
    3: sLable := '@@supercompound';                                                                 //装备合成
    4: sLable := '';
    5: sLable := '@@commoncodense';                                                                 //熔炼宝箱
    6: sLable := '';
    7: begin                                                                                        //黑暗升级
        if (GemStdItems[0] <> nil) then begin
          case GemStdItems[0].StdMode of
            5, 6: sLable := '@@equiplevel';
            10, 11, 15, 58, 81: sLable := '@@defitemlevel';
          else sLable := '@@jewitemlevel';
          end;
        end;
      end;
    8: begin
        sLable := '@@fushi';
        if (nCode = 0) and (nState > 255) then begin
          m_sScriptParam2[0] := IntToStr(nState div 256);
          if (nState mod 256 = 0) then nState := 0 else nState := 1;
        end;
      end;
    9: sLable := '@@hayifu';
    10: sLable := '@@spriterefine';
    11: sLable := '@@upgradeyuanshi';
    12: sLable := '@@HEJINGPO';
    13: sLable := '@@HELONGLING';
    14: sLable := '@@gemxianguan';
  end;
  sLableOK := sLable + 'OK';

  {函数触发开始}
  if (nCode = 0) then begin
    m_sScriptParam[0] := IntToStr(nItemCount);
    for i := 0 to nItemCount - 1 do begin
      m_sScriptParam[i + 1] := IntToStr(GemItems[i].MakeIndex);
      StdItem := UserEngine.GetStdItem(GemItems[i].wIndex);
      if StdItem <> nil then begin
        if (StdItem.StdMode = 44) and (StdItem.Shape = 4) then
          m_sScriptParam[10] := IntToStr(GemItems[i].MakeIndex);
      end;
{$IF USESDK = DEBUG}
      MainOutMessage('物品' + IntToStr(i) + ':' + IntToStr(GemItems[i].MakeIndex));
{$IFEND}
    end;
    if (nState = 1) then begin
      if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
        if (sLable <> '') then ANpc.GotoLable(Self, sLable, False);
      end;
    end else begin
      if (sLableOK <> '') then ANpc.GotoLable(Self, sLableOK, False);
    end;
  end;
end;

//接收Ident 993 Param 1 P1 0 P2 2318 P3 16 Msg ;zfxf@ruvfE  数据部分是放上的物品MakeIndex

procedure TPlayObject.ClientGemSmelt(nState: Integer; RedBaoshi, BlueBaoshi,
  GreenBaoshi: Integer; sItems: string);
var
  ItemMakeIndexs                        : array[0..14] of Integer;
  i, ItemCount                          : Integer;
begin
  FillChar(ItemMakeIndexs[0], SizeOf(Integer) * 15, 0);
  ItemCount := Round(Length(sItems) * 3 / 4) div 4;
  if ItemCount > 0 then
    DeCodeBuffer(sItems, @ItemMakeIndexs, ItemCount * 4);
  for i := 0 to 19 do
    m_sScriptParam[i] := '';
  m_sScriptParam[0] := IntToStr(RedBaoshi);
  m_sScriptParam[1] := IntToStr(BlueBaoshi);
  m_sScriptParam[2] := IntToStr(GreenBaoshi);
  m_sScriptParam[3] := IntToStr(ItemCount - 1);
  for i := 0 to ItemCount - 1 do
    m_sScriptParam[4 + i] := IntToStr(ItemMakeIndexs[i]);
  if m_SMELTNPC <> nil then
    TNormNpc(m_SMELTNPC).GotoLable(Self, '@@gemsmelt', False);
end;

//CM_BUTCH 挖肉

function TPlayObject.ClientGetButchItem(BaseObject: TBaseObject; nX, nY:
  Integer; btDir: byte; var dwDelayTime: LongWord): Boolean;                                        //004DB7E0
var
  N10, n14                              : Integer;
  dwCheckTime                           : LongWord;
begin
  Result := False;
  if (m_wShopItemCount > 0) then Exit;
  dwDelayTime := 0;

  if (not g_Config.boDisableM2SpeedCtrl) then begin
    dwCheckTime := GetTickCount - m_dwTurnTick;
    if dwCheckTime < g_Config.dwTurnIntervalTime then begin
      dwDelayTime := g_Config.dwTurnIntervalTime - dwCheckTime;
      Exit;
    end;
    m_dwTurnTick := GetTickCount;
  end;

  if (abs(nX - m_nCurrX) <= 2) and (abs(nY - m_nCurrY) <= 2) then begin
    if m_PEnvir.IsValidObject(nX, nY, 2, BaseObject) then begin
      if BaseObject.m_boDeath and ((not BaseObject.m_boSkeleton) or ((BaseObject.m_btRaceServer = RC_EVIL) and (BaseObject.m_btRaceImg = 253))) and (BaseObject.m_boAnimal) then begin
        N10 := Random(16) + 5;
        n14 := Random(100);
        Dec(BaseObject.m_nBodyLeathery, N10);
        Dec(BaseObject.m_nMeatQuality, n14);
        if (BaseObject.m_btRaceServer = RC_EVIL) and (BaseObject.m_btRaceImg = 253) then begin      //夺宝心魔
          m_sScriptParam[0] := BaseObject.m_sOriginalName;
          m_sScriptParam[1] := BaseObject.m_sCharName;
          if BaseObject.m_boSkeleton then
            m_sScriptParam[2] := '1'
          else
            m_sScriptParam[2] := '0';                                                               //0:没挖过,1:挖过
          m_sScriptParam[3] := IntToStr(BaseObject.m_nBodyLeathery);
          //尸体坚韧度
          ExecuteScript(g_FunctionNPC, '@弑魔掘宝');
        end;
        if BaseObject.m_nMeatQuality < 0 then BaseObject.m_nMeatQuality := 0;
        if BaseObject.m_nBodyLeathery <= 0 then begin
          BaseObject.m_boSkeleton := True;
          if (BaseObject.m_btRaceServer in [RC_ANIMAL..RC_MONSTER - 1]) then begin
            BaseObject.ApplyMeatQuality();                                                          //计算肉的品质
            BaseObject.SendRefMsg(RM_SKELETON, BaseObject.m_btDirection,
              BaseObject.m_nCurrX, BaseObject.m_nCurrY, 0, '');
          end;
          if not TakeBagItems(BaseObject) then begin
            SysMsg(sYouFoundNothing {未发现任何物品!!!}, c_Red, t_Hint);
          end;
          BaseObject.m_nBodyLeathery := 50;
        end;
        m_dwDeathTick := GetTickCount();
      end;

    end;
    m_btDirection := btDir;
  end;
  SendRefMsg(RM_BUTCH, m_btDirection, m_nCurrX, m_nCurrY, 0, '');
  Result := True;
end;

//取小地图信息

procedure TPlayObject.ClientGetMinMap;
var
  nMinMap                               : Integer;
begin
  nMinMap := m_PEnvir.MinMap;
  if nMinMap > 0 then begin
    SendDefMessage(SM_READMINIMAP_OK, 0, nMinMap, 0, 0, '');
  end else begin
    SendDefMessage(SM_READMINIMAP_FAIL, 0, 0, 0, 0, '');
  end;

end;

//CM_GROUPMODE

procedure TPlayObject.ClientGropuClose;                                                             //004C3C10
begin
  if m_GroupOwner = nil then begin
    m_boAllowGroup := False;
    Exit;
  end;
  if m_GroupOwner <> Self then begin
    m_GroupOwner.DelMember(Self);
    m_boAllowGroup := False;
  end else begin
    SysMsg('如果你想退出,使用编组功能(删除按钮)', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.ClientGuildAddMember(sHumName: string);                                       //004DEDB4
var
  nC                                    : Integer;
  PlayObject                            : TPlayObject;
  Castle                                : TUserCastle;
begin
  nC := 1;                                                                                          //'你没有权利使用这个命令。'
  if IsGuildMaster then begin
    PlayObject := UserEngine.GetPlayObject(sHumName);
    if PlayObject <> nil then begin
      if not TGuild(m_MyGuild).IsFull then begin
        if PlayObject.m_boAllowGuild then begin
          if not TGuild(m_MyGuild).IsMember(sHumName) then begin
            if (PlayObject.m_MyGuild = nil) and (TGuild(m_MyGuild).m_RankList.Count < 400) then begin
              TGuild(m_MyGuild).AddMember(PlayObject);
              UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, TGuild(m_MyGuild).sGuildName);
              PlayObject.m_MyGuild := m_MyGuild;
              PlayObject.m_sGuildRankName := TGuild(m_MyGuild).GetRankName(PlayObject, PlayObject.m_nGuildRankNo);
              PlayObject.RefShowName();
              PlayObject.SysMsg('你已加入行会: ' + TGuild(m_MyGuild).sGuildName + ' 当前封号为: ' + PlayObject.m_sGuildRankName, c_Green, t_Hint);
              //脚本入口函数
              PlayObject.m_sScriptParam[0] := TGuild(m_MyGuild).sGuildName;
              PlayObject.m_sScriptParam[1] := PlayObject.m_sGuildRankName;
              Castle := g_CastleManager.IsCastleMember(PlayObject);
              PlayObject.m_nGuildGold := 0;
              PlayObject.GuildGoldChanged();
              if Castle <> nil then begin
                PlayObject.m_sScriptParam[2] := Castle.m_sName;
                PlayObject.ExecuteScript(g_ManageNPC, '@ADDTOCASTLEGUILD');
              end else
                PlayObject.ExecuteScript(g_ManageNPC, '@ADDTOGUILD');
              nC := 0;
            end else
              nC := 4;                                                                              //'对方已经加入其他行会。'
          end else
            nC := 3;                                                                                //'对方已经加入我们的行会。'
        end else begin
          nC := 5;                                                                                  //'对方不允许加入行会。'
          PlayObject.SysMsg('你拒绝加入行会。 [允许命令为 @' + g_GameCommand.LETGUILD.sCmd + ']', c_Red, t_Hint);
        end;
      end else begin
        nC := 1;
        PlayObject.SysMsg('你所要加入的行会成员已经达到上限!', c_Red, t_Hint);
      end;
    end else nC := 2;                                                                               //'想加入进来的成员应该来面对掌门人。'
  end else
    nC := 1;
  if nC = 0 then begin
    SendDefMessage(SM_GUILDADDMEMBER_OK, 0, 0, 0, 0, '');
  end else begin
    SendDefMessage(SM_GUILDADDMEMBER_FAIL, nC, 0, 0, 0, '');
  end;
end;

procedure TPlayObject.ClientGuildAlly;                                                              //004DF3AC
var
  N8                                    : Integer;
  BaseObjectC                           : TBaseObject;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ClientGuildAlly';
begin
  try
    N8 := -1;
    BaseObjectC := GetPoseCreate();
    if (BaseObjectC <> nil) and
      (BaseObjectC.m_MyGuild <> nil) and
      (BaseObjectC.m_btRaceServer = RC_PLAYOBJECT) and
      (BaseObjectC.GetPoseCreate = Self) then begin
      if TGuild(BaseObjectC.m_MyGuild).m_boEnableAuthAlly then begin
        if BaseObjectC.IsGuildMaster and IsGuildMaster then begin
          if TGuild(m_MyGuild).IsNotWarGuild(TGuild(BaseObjectC.m_MyGuild)) and
            TGuild(BaseObjectC.m_MyGuild).IsNotWarGuild(TGuild(m_MyGuild)) then begin

            TGuild(m_MyGuild).AllyGuild(TGuild(BaseObjectC.m_MyGuild));
            TGuild(BaseObjectC.m_MyGuild).AllyGuild(TGuild(m_MyGuild));

            TGuild(m_MyGuild).SendGuildMsg(TGuild(BaseObjectC.m_MyGuild).sGuildName + '行会已经和您的行会联盟成功。');
            TGuild(BaseObjectC.m_MyGuild).SendGuildMsg(TGuild(m_MyGuild).sGuildName + '行会已经和您的行会联盟成功。');
            TGuild(m_MyGuild).RefMemberName;
            TGuild(BaseObjectC.m_MyGuild).RefMemberName;
            UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber,
              TGuild(m_MyGuild).sGuildName);
            UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber,
              TGuild(BaseObjectC.m_MyGuild).sGuildName);
            N8 := 0;
          end else N8 := -2;
        end else N8 := -3;
      end else N8 := -4;                                                                            //004DF57C
    end;
    if N8 = 0 then begin
      SendDefMessage(SM_GUILDMAKEALLY_OK, 0, 0, 0, 0, '');
    end else begin
      SendDefMessage(SM_GUILDMAKEALLY_FAIL, N8, 0, 0, 0, '');
    end;
  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg);
      MainOutMessage(E.Message);
    end;
  end;
end;

procedure TPlayObject.ClientGuildBreakAlly(sGuildName: string);                                     //004DF604
var
  N10                                   : Integer;
  Guild                                 : TGuild;
begin
  N10 := -1;
  if not IsGuildMaster() then Exit;
  Guild := g_GuildManager.FindGuild(sGuildName);
  if Guild <> nil then begin
    if TGuild(m_MyGuild).IsAllyGuild(Guild) then begin
      TGuild(m_MyGuild).DelAllyGuild(Guild);
      Guild.DelAllyGuild(TGuild(m_MyGuild));
      TGuild(m_MyGuild).SendGuildMsg(Guild.sGuildName + ' 行会与您的行会解除联盟成功!!!');
      Guild.SendGuildMsg(TGuild(m_MyGuild).sGuildName + ' 行会解除了与您行会的联盟!!!');
      TGuild(m_MyGuild).RefMemberName();
      Guild.RefMemberName();
      UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, TGuild(m_MyGuild).sGuildName);
      UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, Guild.sGuildName);
      N10 := 0;
    end else N10 := -2;
  end else N10 := -3;                                                                               //004DF750
  if N10 = 0 then begin
    SendDefMessage(SM_GUILDBREAKALLY_OK, 0, 0, 0, 0, '');
  end else begin
    SendDefMessage(SM_GUILDMAKEALLY_FAIL, 0, 0, 0, 0, '');
  end;
end;

procedure TPlayObject.ClientGuildDelMember(sHumName: string);                                       //004DEFB8
var
  nC                                    : Integer;
  s14                                   : string;
  PlayObject                            : TPlayObject;
  Castle                                : TUserCastle;
begin
  nC := 1;
  if (m_MyGuild <> nil) and IsGuildMaster then begin
    if TGuild(m_MyGuild).IsMember(sHumName) then begin
      if g_GuildManager.MemberOfClan(sHumName) = nil then begin
        if m_sCharName <> sHumName then begin
          if TGuild(m_MyGuild).DelMember(sHumName) then begin
            nC := 0;
          end else
            nC := 4;
        end else begin
          nC := 3;
          s14 := TGuild(m_MyGuild).sGuildName;
          if TGuild(m_MyGuild).CancelGuld(sHumName) then begin
            SysMsg('行会' + s14 + '已被取消!!!', c_Red, t_Hint);
            nC := 0;
          end
        end;
      end else
        nC := 2;
    end else
      SysMsg('你无权删除宗族成员。', c_Red, t_Hint);
  end;

  if nC = 0 then begin
    SendDefMessage(SM_GUILDDELMEMBER_OK, 0, 0, 0, 0, '');
  end else begin
    SendDefMessage(SM_GUILDDELMEMBER_FAIL, nC, 0, 0, 0, '');
  end;
end;

procedure TPlayObject.ClientGuildHome;                                                              //004DEBDC
begin
  ClientOpenGuildDlg();
end;

procedure TPlayObject.ClientGuildMemberList;                                                        //004DEBF0
var
  GuildRank                             : pTGuildRank;
  i, ii                                 : Integer;
  sSENDMSG, sName, sAmbit               : string;
  PlayObject                            : TPlayObject;
begin
  if m_MyGuild = nil then Exit;
  for i := 0 to TGuild(m_MyGuild).m_RankList.Count - 1 do begin
    if i >= 50 then Break;
    GuildRank := TGuild(m_MyGuild).m_RankList.Items[i];
    sSENDMSG := sSENDMSG + '#' + IntToStr(GuildRank.nRankNo) + '/*' + GuildRank.sRankName + '/';
    for ii := 0 to GuildRank.MemberList.Count - 1 do begin
      if ii >= 200 then Break;
      if Length(sSENDMSG) > 5000 then Break;
      sName := GuildRank.MemberList.Keys[ii];
      PlayObject := UserEngine.GetPlayObject(sName);
      if PlayObject <> nil then begin
        if PlayObject.m_btAmbitKind > 2 then begin
          if (PlayObject.m_btAmbitKind mod 2) <> 0 then
            sAmbit := '1'
          else
            sAmbit := '2';
        end else
          sAmbit := '0';
        sSENDMSG := sSENDMSG + '1' + sAmbit + sName + '/';
      end else
        sSENDMSG := sSENDMSG + '00' + sName + '/';
    end;
  end;
  m_defMsg := MakeDefaultMsg(SM_GUILDMEMBERLIST, 0, 0, 0, 0);
  SendSocket(@m_defMsg, EnCodeString(sSENDMSG));
end;

procedure TPlayObject.ClientGuildOfficial(nCode, nRankNo: Integer; sChiefName: string);
var
  ChiefPlayer                           : TPlayObject;
  nPermission                           : Integer;
begin
  if (not (nRankNo in [1..10])) or (sChiefName = '') then Exit;
  if m_MyGuild = nil then Exit;
  ChiefPlayer := UserEngine.GetPlayObject(sChiefName);                                              //行会会长
  if (ChiefPlayer <> nil) then begin
    if nCode = 1 then begin
      if m_nGuildGold >= nGuildOfficialPrice[nRankNo] then begin
        TGuild(m_MyGuild).GetOfficial(nRankNo, sGuildOfficial[nRankNo], m_sCharName);               //任命职位
        Dec(m_nGuildGold, nGuildOfficialPrice[nRankNo]);
        GuildGoldChanged;
        if g_boGameLogGuildGold then begin
          AddGameDataLog(Format(g_sGameLogMsg, [LOG_GUILDGOLD,
            m_sMapName,
              m_nCurrX,
              m_nCurrY,
              m_sCharName,
              '行会银两',
              nGuildOfficialPrice[nRankNo],
              '-',
              '官职任命']));
        end;
      end else
        SysMsg('行会银两不足' + IntToStr(nGuildOfficialPrice[nRankNo]) + '个,无法任命该职位!', c_Red, t_Hint);
      SysMsg('恭喜你获得了新的行会职位!', c_Green, t_Hint);
      ChiefPlayer.SysMsg(m_sCharName + '被任命为' + sGuildOfficial[nRankNo], c_Red, t_Hint);
    end else begin
      ChiefPlayer.SysMsg(m_sCharName + '拒绝被任命为' + sGuildOfficial[nRankNo], c_Red, t_Hint);
    end;
  end;
end;

procedure TPlayObject.ClientGuildUpdateNotice(sNotict: string);
var
  SC                                    : string;
begin
  if (m_MyGuild = nil) or (m_nGuildRankNo <> 1) then Exit;
  TGuild(m_MyGuild).NoticeList.Clear;
  while (sNotict <> '') do begin
    sNotict := GetValidStr3(sNotict, SC, [#$D]);
    TGuild(m_MyGuild).NoticeList.Add(SC);
  end;
  TGuild(m_MyGuild).UpdateGuildFile;
  UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber,
    TGuild(m_MyGuild).sGuildName);
  ClientOpenGuildDlg();
end;

procedure TPlayObject.ClientGuildUpdateRankInfo(sRankInfo: string);
var
  nC                                    : Integer;
begin
  if (m_MyGuild = nil) or (m_nGuildRankNo <> 1) then Exit;

  nC := TGuild(m_MyGuild).UpdateRankNew(sRankInfo);
  if nC = 0 then begin
    UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, TGuild(m_MyGuild).sGuildName);
    ClientGuildMemberList();
  end else begin
    if nC <= -2 then begin
      SendDefMessage(SM_GUILDRANKUPDATE_FAIL, nC, 0, 0, 0, '');
    end;
  end;

end;

//检测是否允许指定动作

function TPlayObject.CheckCanOperate(Action: TClientAction; nKey: Integer = 0): Boolean;
begin
  Result := False;

  if m_boGodCallBoss and m_boSuperMan then m_boSuperMan := False;
  //  if m_boInMagicCast then begin
  //    m_boInMagicCast := False;
  //    SendRefMsg(RM_MAGICFIREFAIL, 0, 0, 0, 0, '');
  //  end;

  if m_boDeath or m_boGhost then Exit;

{ if nKey = SKILL_186 then begin
    if (m_wStatusTimeArr[STATE_SILENCE] = 0) then
      Result := True;
    Exit;
  end; }

  if (m_wStatusTimeArr[STATE_FEAR {恐惧}] > 0) or (m_wStatusTimeArr[POISON_DONTMOVE] <> 0) or (m_wStatusTimeArr[STATE_FREEZECHAIN] <> 0) then Exit;

  case Action of
    cHit: begin
        if ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanHit) then Exit;
      end;
    cRun: begin
        if (m_wStatusTimeArr[STATE_FREEZE {冰冻}] <> 0) or (m_wStatusTimeArr[STATE_FIXEDBODY] <> 0) or ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanRun) then Exit;
      end;
    cWalk: begin
        if (m_wStatusTimeArr[STATE_FREEZE {冰冻}] <> 0) or (m_wStatusTimeArr[STATE_FIXEDBODY] <> 0) or ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanWalk) then Exit;
      end;
    cDigUp: begin
        if (m_wStatusTimeArr[STATE_FREEZE {冰冻}] <> 0) or (m_wStatusTimeArr[STATE_FIXEDBODY] <> 0) or ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanHit) then Exit;
      end;
    cTurn: begin
        if (m_wStatusTimeArr[STATE_FREEZE {冰冻}] <> 0) or (m_wStatusTimeArr[STATE_FIXEDBODY] <> 0) or ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanRun) then Exit;
      end;
    cMagHit: begin
        if (m_wStatusTimeArr[STATE_SILENCE {沉默}] <> 0) or ((m_wStatusTimeArr[POISON_STONE] <> 0) and not g_Config.ClientConf.boParalyCanSpell) then Exit;
      end;
  end;

  Result := True;
end;

//物理攻击命令的处理,包括
// CM_HIT、CM_HEAVYHIT、CM_BIGHIT、CM_POWERHIT、CM_LONGHIT、CM_WIDEHIT
// CM_FIREHIT、CM_CRSHIT、CM_TWNHIT、CM_42HIT、CM_42HIT、CM_3026
// 3014 普通攻击
// 3018 功杀
// 3019 刺杀
// 3024 半月
// 3025 烈火

function TPlayObject.ClientHitXY(wIdent: word; nX, nY, nDir, nMagicID: Integer;
  boLateDelivery: Boolean; var dwDelayTime: LongWord): Boolean;                                     //004CB7F8
var
  n14, n18                              : Integer;
  StdItem                               : pTStdItem;
  dwAttackTime, dwCheckTime             : LongWord;
  nPinjunTime                           : Integer;
  AttackTarget                          : TBaseObject;
{$IF CATEXCEPTION = TRYEXCEPTION}
  nCheckCode                            : Integer;
{$IFEND}
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ClientHitXY Code=%d';
  sHint1                                = '摆摊或变身模式下禁止攻击';
  sHint2                                = '骑马禁止攻击';
  sHint3                                = '死亡或被麻痹禁止攻击';
  sHint4                                = '5次攻击超速!限制:%d,当前:%d';
  sHint5                                = '攻击忙复位!!!';
  sHint6                                = '攻击不忙!!!';
begin
  Result := False;
  dwDelayTime := 0;
{$IF CATEXCEPTION = TRYEXCEPTION}
  nCheckCode := 0;
{$IFEND}
  if not m_boCanHit or m_boCatapultAttackMode then Exit;
{$IF CATEXCEPTION = TRYEXCEPTION}
  try
{$IFEND}
    if m_boPneuma and m_PEnvir.m_MapFlag.boNoPneuma then Exit;                                      //元神在不允许释放的地图,禁止攻击
    if (m_wShopItemCount > 0) then begin
      if g_Config.boOldClientShowHiLevel then SysMsg(sHint1, c_Blue, t_Hint);
      Exit;
    end;
    if (m_wBianshenAppr > 0) and (m_boAttackMode = False) then begin
      if g_Config.boOldClientShowHiLevel then SysMsg(sHint1, c_Blue, t_Hint);                       //2016.06.22 支持ChangeAppr变身支持攻击
      Exit;
    end;
    if (m_boRideOn and not m_boRideFightOn) then begin
      if g_Config.boOldClientShowHiLevel then SysMsg(sHint2, c_Blue, t_Hint);
      Exit;                                                                                         //骑马不允许攻击
    end;
    if not CheckCanOperate(cHit) then begin
      if g_Config.boOldClientShowHiLevel then SysMsg(sHint3, c_Blue, t_Hint);
      Exit;
    end;

    //10指令时间控制
    if (not g_Config.boDisableM2SpeedCtrl) then begin
      if m_nHitCount = 0 then m_FirstHitTick := GetTickCount;
      Inc(m_nHitCount);
      if m_nHitCount >= 6 then begin
        nPinjunTime := (GetTickCount - m_FirstHitTick) div 5;
        m_FirstHitTick := GetTickCount;
        m_nHitCount := 0;
        if nPinjunTime < g_Config.n10HitTIme then begin
          if m_boTestSpeedMode then
            SysMsg(Format(sHint4, [g_Config.n10HitTIme, nPinjunTime]), c_Red, t_Hint);
          Exit;
        end;
      end;

{$IF CATEXCEPTION = TRYEXCEPTION}
      nCheckCode := 1;
{$IFEND}
      if (not boLateDelivery) then begin
        if not CheckActionStatus(wIdent, dwDelayTime) then begin
          m_boFilterAction := False;
          Exit;
        end;
        m_boFilterAction := True;
        dwAttackTime := _Max(0, Integer(g_Config.dwHitIntervalTime) - m_nHitSpeed * g_Config.ClientConf.btItemSpeed); //防止负数出错
        dwCheckTime := GetTickCount - m_dwAttackTick;
        if dwCheckTime < dwAttackTime then begin
          if m_dwWalkTick = 0 then
            Inc(m_dwAttackCount);
          dwDelayTime := dwAttackTime - dwCheckTime;
          if dwDelayTime > g_Config.dwDropOverSpeed then begin
            if m_dwAttackCount >= 4 then begin
              m_dwAttackTick := GetTickCount();
              m_dwAttackCount := 0;
              dwDelayTime := g_Config.dwDropOverSpeed;
              if m_boTestSpeedMode then
                SysMsg(sHint5 + IntToStr(dwDelayTime), c_Red, t_Hint);
            end else m_dwAttackCount := 0;
            Exit;
          end else begin
            if m_boTestSpeedMode then
              SysMsg(sHint6 + IntToStr(dwDelayTime), c_Red, t_Hint);
            Exit;
          end;
        end;
      end;
    end;

{$IF CATEXCEPTION = TRYEXCEPTION}
    nCheckCode := 2;
{$IFEND}

    CheckProwlMagic();                                                                              //检测是否有潜行

    if (nX = m_nCurrX) and (nY = m_nCurrY) or (wIdent = CM_HIT) then begin
      Result := True;
      m_dwAttackTick := GetTickCount();
      if (wIdent = CM_HEAVYHIT) and (m_UseItems[U_WEAPON].Dura > 0) then begin                      //挖矿
        if g_Config.boStartMapEvent then begin
          if m_btRaceServer = RC_PLAYOBJECT then StartMapEventOfMine();
        end;

        if GetFrontPosition(n14, n18) and not m_PEnvir.CanWalk(n14, n18, False) then begin
          StdItem := UserEngine.GetStdItem(m_UseItems[U_WEAPON].wIndex);
          if (StdItem <> nil) and (StdItem.Shape = 19) then begin
            if PileStones(n14, n18) then SendSocket(nil, sSTATUS_DIG);

            Dec(m_nHealthTick, 30);
            Dec(m_nSpellTick, 50);
            m_nSpellTick := _Max(0, m_nSpellTick);
            Dec(m_nPerHealth, 2);
            Dec(m_nPerSpell, 2);
            Exit;
          end;
        end
      end else if (wIdent = CM_HIT) and (m_UseItems[U_WEAPON].Dura > 0) then begin
{$IF CATEXCEPTION = TRYEXCEPTION}
        nCheckCode := 3;
{$IFEND}
        AttackTarget := GetPoseCreate();
        if (AttackTarget <> nil) and not AttackTarget.m_boDeath and not AttackTarget.m_boGhost and (AttackTarget.m_wAppr in [151..155]) then begin
          StdItem := UserEngine.GetStdItem(m_UseItems[U_WEAPON].wIndex);
          if (StdItem <> nil) and (StdItem.Shape = 39) then begin
            if (m_Horse = nil) and (Random(10) = 0) and
              ((AttackTarget.m_wAppr <> 152) or (IsGuildMaster)) then begin                         //抓马成功,其中雪龙只有行会掌门才能抓
              HorseName := FilterShowName(AttackTarget.m_sCharName);
              m_Horse := MakeSlave(HorseName, 0, 0, 100, 24 * 60 * 60, -1);
              if m_Horse <> nil then begin
                m_btHorseType := AttackTarget.m_wAppr - 150;

                if m_PEnvir.MoveToMovingObject(m_Horse.m_nCurrX, m_Horse.m_nCurrY, m_Horse, AttackTarget.m_nCurrX, AttackTarget.m_nCurrY, True) > 0 then begin
                  m_Horse.m_nCurrX := AttackTarget.m_nCurrX;
                  m_Horse.m_nCurrY := AttackTarget.m_nCurrY;
                  m_Horse.m_btDirection := AttackTarget.m_btDirection;
                end;
                m_Horse.TurnTo(m_btDirection);
                SendDefMessage(34977, m_Horse.m_wAppr, 612, 1, 0, '');
                SendRefMsg(RM_SITDOWN, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), GetFeatureToLong(Self), 0, '');
                AttackTarget.MakeGhost;
                ExecuteScript(g_FunctionNPC, '@抓马成功');
              end;
              Exit;
            end;
            Exit;
          end;
        end;
      end;
{$IF CATEXCEPTION = TRYEXCEPTION}
      nCheckCode := 4;
{$IFEND}

      if wIdent = CM_HIT then AttackDir(nil, 0, nDir);                                              //普通攻击0
      if wIdent = CM_HEAVYHIT then AttackDir(nil, 1, nDir);                                         //普通攻击1 挖矿
      if wIdent = CM_BIGHIT then AttackDir(nil, 2, nDir);                                           //普通攻击2
      if wIdent = CM_POWERHIT then AttackDir(nil, 3, nDir);                                         //攻杀剑法
      if wIdent = CM_LONGHIT then AttackDir(nil, 4, nDir);                                          //刺杀剑术
      if wIdent = CM_WIDEHIT then AttackDir(nil, 5, nDir);                                          //半月弯刀
      if wIdent = CM_FIREHIT then AttackDir(nil, 7, nDir);                                          //烈火剑法
      if wIdent = CM_CRSHIT then AttackDir(nil, 8, nDir);
      if wIdent = CM_TWNHIT then AttackDir(nil, 9, nDir);
      //      if wIdent = CM_42HIT then AttackDir(nil, 10, nDir);
{$IF CATEXCEPTION = TRYEXCEPTION}
      nCheckCode := 5;
{$IFEND}
      if wIdent = CM_3026 then begin                                                                //战士新技能的攻击包处理:血影刀法\抱月刀\ 残影刀法     破击剑法、破盾斩
        case nMagicID of
          SKILL_59: AttackDir(nil, 12, nDir);                                                       //破击剑法
          SKILL_60: AttackDir(nil, 13, nDir);                                                       //破盾斩
          SKILL_43: AttackDir(nil, 14, nDir);                                                       //抱月刀
          SKILL_44: AttackDir(nil, 15, nDir);                                                       //雷霆剑
          SKILL_40: AttackDir(nil, 16, nDir);                                                       //残影刀法
          SKILL_41: AttackDir(nil, 17, nDir);                                                       //血影刀法
          SKILL_88: AttackDir(nil, 18, nDir);                                                       //强化攻杀
        end;
      end;

{$IF CATEXCEPTION = TRYEXCEPTION}
      nCheckCode := 6;
{$IFEND}
      if (m_MagicSkills[SKILL_YEDO] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
        Dec(m_btAttackSkillCount);
        if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
          m_boPowerHit := True;
          SendSocket(nil, '+PWR');
        end;

        //出刀几率
        if m_btAttackSkillCount <= 0 then begin
          if g_Config.boUseXMLMagicSkill then begin
            //if (m_MagicSkills[SKILL_88] <> nil) then
            //  m_btAttackSkillCount := g_MagicSkill[SKILL_88].btLv[m_MagicSkills[SKILL_88].btLevel].btVal[5]
            //else
            m_btAttackSkillCount := g_MagicSkill[SKILL_YEDO].btLv[m_MagicSkills[SKILL_YEDO].btLevel].btVal[13];
          end else begin
            //if (m_MagicSkills[SKILL_88] <> nil) then
            //  m_btAttackSkillCount := 10 - _MIN(m_MagicSkills[SKILL_88].btLevel, 3)
            //else
            m_btAttackSkillCount := 8 - _MIN(m_MagicSkills[SKILL_YEDO].btLevel, 3);
          end;
          m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
        end;
      end else if (m_MagicSkills[SKILL_40] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
        Dec(m_btAttackSkillCount);
        if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
          m_boPowerHit := True;
          SendSocket(nil, '+VIS');
        end;

        if m_btAttackSkillCount <= 0 then begin
          if g_Config.boUseXMLMagicSkill then
            m_btAttackSkillCount := g_MagicSkill[SKILL_40].btLv[m_MagicSkills[SKILL_40].btLevel].btVal[13]
          else
            m_btAttackSkillCount := 8 - _MIN(m_MagicSkills[SKILL_40].btLevel, 3);

          m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
        end;
      end else if (m_MagicSkills[SKILL_41] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
        Dec(m_btAttackSkillCount);
        if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
          m_boPowerHit := True;
          SendSocket(nil, '+SHAD');
        end;

        if m_btAttackSkillCount <= 0 then begin
          if g_Config.boUseXMLMagicSkill then
            m_btAttackSkillCount := g_MagicSkill[SKILL_41].btLv[m_MagicSkills[SKILL_41].btLevel].btVal[9]
          else
            m_btAttackSkillCount := 8 - _MIN(m_MagicSkills[SKILL_41].btLevel, 3);

          m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
        end;
      end;

{$IF CATEXCEPTION = TRYEXCEPTION}
      nCheckCode := 7;
{$IFEND}
      Dec(m_nHealthTick, 30);
      Dec(m_nSpellTick, 100);
      m_nSpellTick := _Max(0, m_nSpellTick);
      Dec(m_nPerHealth, 2);
      Dec(m_nPerSpell, 2);
    end;
{$IF CATEXCEPTION = TRYEXCEPTION}
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
{$IFEND}
end;

//骑马(CM_HORSERUN 命令的处理)
(*
function TPlayObject.ClientHorseRunXY(wIdent: word; nX, nY: Integer;
  boLateDelivery: Boolean; var dwDelayTime: LongWord): Boolean;
var
  n14                              : Integer;
  dwCheckTime                      : LongWord;
resourcestring
  sHint1                           = '马跑步忙复位!!!';
  sHint2                           = '马跑步忙!!!';
begin
  Result := False;
  dwDelayTime := 0;
  Exit;
  if not m_boCanRun or (m_wShopItemCount > 0) then Exit;

  if not CheckCanOperate(cHorseRun) then Exit;

  if (not g_Config.boDisableM2SpeedCtrl) and (not boLateDelivery) then begin
    if not CheckActionStatus(wIdent, dwDelayTime) then begin
      m_boFilterAction := False;
      Exit;
    end;
    m_boFilterAction := True;
    dwCheckTime := GetTickCount - m_dwMoveTick;
    if dwCheckTime < g_Config.dwRunIntervalTime then begin
      Inc(m_dwMoveCount);
      dwDelayTime := g_Config.dwRunIntervalTime - dwCheckTime;
      if dwDelayTime > g_Config.dwDropOverSpeed then begin
        if m_dwMoveCount >= 4 then begin
          m_dwMoveTick := GetTickCount();
          m_dwMoveCount := 0;
          dwDelayTime := g_Config.dwDropOverSpeed;
          if m_boTestSpeedMode then
            SysMsg(sHint1 + IntToStr(dwDelayTime), c_Red, t_Hint);
        end else m_dwMoveCount := 0;
        Exit;
      end else begin
        if m_boTestSpeedMode then
          SysMsg(sHint2 + IntToStr(dwDelayTime), c_Red, t_Hint);
        Exit;
      end;
    end;
  end;

  m_dwMoveTick := GetTickCount();
  m_boMoveSuccess := False;
  {$IF USESDK = DEBUG}
  SysMsg(Format('当前X:%d 当前Y:%d 目标X:%d 目标Y:%d', [m_nCurrX, m_nCurrY, nX, nY]), c_Green, t_Hint);
  {$IFEND}
  n14 := GetNextDirection(m_nCurrX, m_nCurrY, nX, nY);
  if HorseRunTo(n14, False) then begin
    if m_boTransparent and (m_boHideMode) then
      m_wStatusTimeArr[STATE_TRANSPARENT] := 1;                                                     //004CB212
    if m_boMoveSuccess or ((m_nCurrX = nX) and (m_nCurrY = nY)) then
      Result := True;
    Dec(m_nHealthTick, 60);
    Dec(m_nSpellTick, 10);
    m_nSpellTick := _Max(0, m_nSpellTick);
    Dec(m_nPerHealth);
    Dec(m_nPerSpell);
  end else begin
    m_dwMoveCount := 0;
    m_dwMoveCountA := 0;
  end;
end;
*)

procedure TPlayObject.ClientInjectPowerToTreasureBox(nPoint: Integer);
var
  tm, tm2                               : DWORD;
  d                                     : TDateTime;
  n                                     : Integer;
begin
  if (nPoint <= 0) or (m_TreasureBoxItem = nil) then Exit;
  if (m_Abil.wNimBusPoint < nPoint) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, Format('你的灵力不足%d点,无法为灵犀宝盒注入灵力', [nPoint]));
    Exit;
  end;
  Dec(m_Abil.wNimBusPoint, nPoint);
  RecalcAbilitys();
  SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  tm := MakeLong(MakeWord(m_TreasureBoxItem.btValue[4], m_TreasureBoxItem.btValue[5]), MakeWord(m_TreasureBoxItem.btValue[6], m_TreasureBoxItem.btValue[7]));
  tm2 := DateTimeToWolTimeEx(Now);
  if (tm2 > tm) then tm := tm2;
  n := Round(7 * nPoint / m_TreasureBoxItem.DuraMax);
  d := AddDateTimeOfDay(WolTimeToDateTime(tm), n + 1);
  tm := DateTimeToWolTimeEx(d);                                                                     //到期时间
  Move(tm, m_TreasureBoxItem.btValue[4], 4);
  ClientQueryTreasureBoxItems(False);
  SendDefMessage(SM_INFORMATION, 0, 0, 0, 0,
    Format('你已经为宝盒注入%d点灵力\(当前灵力可维持宝盒到%s)', [nPoint, FormatDateTime('yyyy-mm-dd hh:mm:ss', d)]));
end;

procedure TPlayObject.ClientInput(nParam1: Integer; Data: string);
var
  NPC                                   : TNormNpc;
  s18, sLable                           : string;
  nCheckCode                            : Integer;
begin
  nCheckCode := 0;
  try
    if m_boDeath or m_boGhost then Exit;

    if Length(Data) > 500 then Exit;
    nCheckCode := 1;
    if m_nQueryValIdx in [0..99] then begin
      if m_btQueryValType = 1 then                                                                  //整数型数据保存到M变量中
        m_nMval[m_nQueryValIdx] := Str_ToInt(Data, 0)
      else begin                                                                                    //字符型变量保存到S变量中
        if CheckFilterWords(Data) then begin
          SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '输入内容含有非法字符!');
          Exit;
        end;
        m_dyStrVal[m_nQueryValIdx] := Data;
      end;
    end else begin
      m_sQueryData := Data;
    end;

    if m_sNextLabel = '' then Exit;
    nCheckCode := 2;
    NPC := UserEngine.FindMerchant(m_QUERYNPC);
    if NPC = nil then
      NPC := UserEngine.FindNPC(m_QUERYNPC);

    if NPC = nil then Exit;
    nCheckCode := 3;
    if (IsEnvir(NPC.m_PEnvir) and
      (abs(NPC.m_nCurrX - m_nCurrX) < 15) and
      (abs(NPC.m_nCurrY - m_nCurrY) < 15)) or (NPC.m_boIsHide) then begin
      nCheckCode := 4;
      if CompareText(m_sNextLabel, sBUILDGUILDNOW) = 0 then begin                                   //建立行会
        nCheckCode := 5;
        if NPC is TGuildOfficial then
          TGuildOfficial(NPC).ReQuestBuildGuild(Self, Data);
      end else if CompareText(m_sNextLabel, sSCL_GUILDWAR) = 0 then begin                           //行会战争
        nCheckCode := 6;
        if NPC is TGuildOfficial then
          TGuildOfficial(NPC).ReQuestGuildWar(Self, Data);
      end else if CompareText(m_sNextLabel, sWITHDRAWAL) = 0 then begin                             //取回金币
        nCheckCode := 7;
        if NPC.m_Castle = nil then begin
          SysMsg('NPC不属于城堡!!!', c_Red, t_Hint);
          Exit;
        end;
        case TUserCastle(NPC.m_Castle).WithDrawalGolds(Self, Str_ToInt(Data, 0))
          of
          -4: s18 := '输入的金币数不正确!!!';
          -3: s18 := '您无法携带更多的东西了。';
          -2: s18 := '该城内没有这么多金币.';
          -1: s18 := '只有行会 ' + TUserCastle(NPC.m_Castle).m_sOwnGuild + ' 的掌门人才能使用!!!';
          1: begin
              s18 := '取回金币成功!';
              NPC.GotoLable(Self, sMAIN, False);
            end;
        end;
        SendMsg(NPC, RM_MENU_OK, 0, Integer(NPC), 0, 0, s18);
      end else if CompareText(m_sNextLabel, sRECEIPTS) = 0 then begin                               //存放金币
        nCheckCode := 8;
        if NPC.m_Castle = nil then begin
          SysMsg('NPC不属于城堡!!!', c_Red, t_Hint);
          Exit;
        end;
        case TUserCastle(NPC.m_Castle).ReceiptGolds(Self, Str_ToInt(Data, 0)) of
          -4: s18 := '输入的金币数不正确!!!';
          -3: s18 := '你已经达到在城内存放货物的限制了。';
          -2: s18 := '你没有那么多金币.';
          -1: s18 := '只有行会 ' + TUserCastle(NPC.m_Castle).m_sOwnGuild + ' 的掌门人才能使用!!!';
          1: begin
              s18 := '存放金币成功!';
              NPC.GotoLable(Self, sMAIN, False);
            end;
        end;
        SendMsg(NPC, RM_MENU_OK, 0, Integer(NPC), 0, 0, s18);
      end else begin
        nCheckCode := 9;
        sLable := m_sNextLabel;
        m_sNextLabel := '';
        NPC.GotoLable(Self, sLable, False);                                                         //其他标签
      end;
    end;
  except
    on E: Exception do begin
      MainOutMessage(Format('TPlayObject.ClientInput:: nParam1: %d; Data: %s; Lable: %s Code: %d', [nParam1, Data, sLable, nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
end;

//炼药

procedure TPlayObject.ClientMakeDrugItem(NPC: TObject; nItemName: string);
//004DCAF8
var
  Merchant                              : TMerchant;
begin
  Merchant := UserEngine.FindMerchant(NPC);
  if (Merchant = nil) or (not Merchant.m_boMakeDrug) then Exit;
  if (IsEnvir(Merchant.m_PEnvir) and
    (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
    (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) then
    Merchant.ClientMakeDrugItem(Self, nItemName);
end;

//CM_MERCHANTDLGSELECT 选择标签

procedure TPlayObject.ClientMerchantDlgSelect(nParam1: Integer; sMsg: string; nType: Integer);
var
  NPC                                   : TNormNpc;
begin
  if m_boDeath or m_boGhost then Exit;

  //  if nParam1 = 0 then begin
  //    ExecuteScript(g_FunctionNPC, sMsg);
  //    Exit;
  //  end;

    //通灵塔NPC
  case nParam1 of
    -6:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('通灵塔跳转:' + sMsg);
{$IFEND}
        if (g_GuildTowerNPC <> nil) and (sMsg <> '') then g_GuildTowerNPC.UserSelect(Self, Trim(sMsg));
        Exit;
      end;
    -7:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('商城活动领奖:' + sMsg);
{$IFEND}
     // GetScriptLabel('@VIP每日福利', false);
        if (g_WolShopNPC <> nil) and (sMsg <> '') then ExecuteScript(g_WolShopNPC, '@_商城_活动领奖');
        Exit;
      end;
    -12:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('时光倒流VIP每日福利:' + sMsg);
{$IFEND}
     // GetScriptLabel('@VIP每日福利', false);
        if (g_ManageNPC <> nil) and (sMsg <> '') then ExecuteScript(g_ManageNPC, '@_VIP_每日福利');
        Exit;
      end;
    -13:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('时光倒流VIP神行千里:' + sMsg);
{$IFEND}
     // GetScriptLabel('@VIP神行千里', false);
        if (g_ManageNPC <> nil) and (sMsg <> '') then ExecuteScript(g_ManageNPC, '@_VIP_神行千里');
        Exit;
      end;
    -14:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('时光倒流VIP神龙之魂:' + sMsg);
{$IFEND}
     // GetScriptLabel('@VIP神龙之魂', false);
        if (g_ManageNPC <> nil) and (sMsg <> '') then ExecuteScript(g_ManageNPC, '@_VIP_神龙之魂');
        Exit;
      end;
    -15:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('未知:' + sMsg);
{$IFEND}
    //  GetScriptLabel('@未知', false);
        if (g_FunctionNPC <> nil) and (sMsg <> '') then ExecuteScript(g_FunctionNPC, '@未知');
        Exit;
      end;
    -16:
      begin
{$IF USESDK = DEBUG}
        MainOutMessage('战斗力:' + sMsg);
{$IFEND}
        m_BattleVal.BattleVal := m_BattleVal.nMinVal[0] + m_BattleVal.nMinVal[1] +
          m_BattleVal.nMinVal[2] + m_BattleVal.nMinVal[3] + m_BattleVal.nMinVal[4];
        SendDefMessage(SM_BATTLEVAL, Integer(Self), m_BattleVal.BattleVal, 0, 0,
          EnCodeBuffer(@m_BattleVal, SizeOf(TBattleData)), True);
        if (g_ManageNPC <> nil) and (sMsg <> '') then
        begin
          if nType > 0 then
            ExecuteScript(g_ManageNPC, '@_战斗力_HOME')
          else
            g_ManageNPC.UserSelect(self, sMsg);
        end;
        Exit;
      end;
  else
    begin
{$IF USESDK = DEBUG}
      MainOutMessage('Code: ' + inttostr(nParam1) + '其他NPC跳转:' + sMsg);
{$IFEND}
    end;

  end;

  NPC := UserEngine.FindMerchant(TObject(nParam1));
  if NPC = nil then NPC := UserEngine.FindNPC(TObject(nParam1));
  if NPC = nil then Exit;
  if (IsEnvir(NPC.m_PEnvir) and
    (abs(NPC.m_nCurrX - m_nCurrX) < 15) and
    (abs(NPC.m_nCurrY - m_nCurrY) < 15)) or (NPC.m_boIsHide) then
    NPC.UserSelect(Self, Trim(sMsg));
end;

//计算商品价格

procedure TPlayObject.ClientMerchantQuerySellPrice(nParam1, nMakeIndex: Integer;
  sMsg: string);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  UserItem18                            : pTUserItem;
  Merchant                              : TMerchant;
  sName                                 : string;
begin
  UserItem18 := nil;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if UserItem.MakeIndex = nMakeIndex then begin
      //取自定义物品名称
      sName := '';
      ItemUnit.GetCustomItemName(UserItem, sName);

      if (CompareText(sMsg, sName) = 0) then begin
        UserItem18 := UserItem;
        Break;
      end;
    end;
  end;
  if UserItem18 = nil then begin
    SendDefMessage(618, nMakeIndex, 1, 0, 0, '');
    Exit;
  end;
  Merchant := UserEngine.FindMerchant(TObject(nParam1));
  if Merchant = nil then Exit;
  if (IsEnvir(Merchant.m_PEnvir) and
    (Merchant.m_boSell) and
    (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
    (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) then
    Merchant.ClientQuerySellPrice(Self, UserItem18);
end;

procedure TPlayObject.ClientNamedStore(nParam1: Integer; nMakeIndex: Integer);
var
  NPC                                   : TNormNpc;
  i, j                                  : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  retMsg, sLable                        : string;
  tm                                    : DWORD;
label
  return;
begin
  retMsg := '';
  if m_boDeath or m_boGhost then goto return;
  NPC := UserEngine.FindMerchant(TObject(nParam1));
  if NPC = nil then NPC := UserEngine.FindNPC(TObject(nParam1));
  if (NPC = nil) and not (m_nSpotDlgMode in [100..112, 200, 201, 202]) then
    Exit;
  sLable := m_sNextLabel;
  m_sNextLabel := '';
  if (m_nSpotDlgMode in [100..112, 200, 201, 202]) or
    ((IsEnvir(NPC.m_PEnvir) and
    (abs(NPC.m_nCurrX - m_nCurrX) < 15) and
    (abs(NPC.m_nCurrY - m_nCurrY) < 15)) or (NPC.m_boIsHide)) then begin
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := pTUserItem(m_ItemList.Items[i]);
      if UserItem.MakeIndex = nMakeIndex then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if (StdItem = nil) then goto return;
        if (m_nSpotDlgMode = 0) and (StdItem.StdMode = 3) and ((StdItem.Shape = 15) or ((StdItem.Shape = 17) and ((StdItem.Looks = 729) or (StdItem.Looks = 942)))) then begin //记录回城点
          for j := 0 to 11 do
            UserItem.btValue[j] := 0;
          UserItem.btValue[0] := LoByte(m_nStoreX);
          UserItem.btValue[1] := HiByte(m_nStoreX);
          UserItem.btValue[2] := LoByte(m_nStoreY);
          UserItem.btValue[3] := HiByte(m_nStoreY);
          for j := 1 to _MIN(11, Length(m_sStoreName)) do
            UserItem.btValue[j + 3] := byte(m_sStoreName[j]);
          //更新物品
          SendUpdateItem(UserItem);
          if (sLable <> '') then
            NPC.GotoLable(Self, sLable, False);
        end else if (m_nSpotDlgMode = 1) and (StdItem.StdMode = 45) and
          (StdItem.AniCount in [1..5]) then begin                                                   //宝石仓库
          //检查宝石仓库容量
          if m_wGemCount[StdItem.AniCount - 1] >= 200 then begin
            retMsg := '仓库中已经有200颗这种宝石了,无法放下更多的宝石!';
            goto return;
          end;
          Inc(m_wGemCount[StdItem.AniCount - 1]);

          SendDefMessage(SM_STORAGE_OK, 0, 0, 0, 0, '');                                            //0419
          if StdItem.boGameLog = 1 then
            AddGameDataLog('1' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              '0');

          if (sLable <> '') and (NPC <> nil) then
            NPC.GotoLable(Self, sLable, False);

          Dispose(UserItem);
          m_ItemList.Delete(i);
          WeightChanged();

        end else if (m_nSpotDlgMode = 3) and (StdItem.StdMode = 33) and (StdItem.Shape = 0) then begin //绑马牌
          if m_btSetHorseType > 0 then begin
            if UserItem.btValue[0] <> 0 then begin
              retMsg := '你提供的马牌不是空的马牌。';
              Break;
            end;
          end else if UserItem.btValue[0] = 0 then begin
            retMsg := '你提供的马牌是空的马牌,不需要清空。';
            Break;
          end;
          for j := 0 to 12 do
            UserItem.btValue[j] := 0;
          UserItem.btValue[0] := m_btSetHorseType;
          if m_btSetHorseType > 0 then
            for j := 1 to Length(m_sHorseName) do
              UserItem.btValue[j] := byte(m_sHorseName[j]);
          UserItem.Dura := UserItem.DuraMax;
          SendUpdateItem(UserItem);
          if (sLable <> '') and (NPC <> nil) then
            NPC.GotoLable(Self, sLable, False);
        end else if (m_nSpotDlgMode = 4) and (StdItem.StdMode = 33) and (StdItem.Shape = 0) then begin //修理马牌
          if UserItem.btValue[0] = 0 then begin
            retMsg := '你提供的马牌是空马牌。';
            Break;
          end;
          UserItem.Dura := UserItem.DuraMax;
          SendUpdateItem(UserItem);
          if (sLable <> '') then
            NPC.GotoLable(Self, sLable, False);
        end else if (m_nSpotDlgMode = 6) then begin                                                 //任意物品 ,触发当前NPC中的[@物品名称]脚本标签
          try
            m_sStoreName := StdItem.Name;                                                           //保存物品名字
            m_nStoreMakeIndex := nMakeIndex;
            m_sScriptParam[0] := StdItem.Name;
            m_sScriptParam[1] := IntToStr(nMakeIndex);
            if not NPC.GotoLable(Self, '@' + StdItem.Name, False) then
              if sLable <> '' then begin
                m_sNextLabel := sLable;
                NPC.GotoLable(Self, sLable, False);
              end;
          except
          end;
        end else
          retMsg := '你提供的物品不正确。';
        sLable := '';
        Break;
      end;
    end;
  end;
  return:
  SendMsg(nil, $9590, 1, $FF, 0, 0, retMsg);
end;

procedure TPlayObject.ClientOpenDoor(nX, nY: Integer);                                              //004DABD4
var
  Door                                  : pTDoorInfo;
  Castle                                : TUserCastle;
begin
  Door := m_PEnvir.GetDoor(nX, nY);
  if Door = nil then Exit;
  Castle := g_CastleManager.IsCastleEnvir(m_PEnvir);
  if (Castle = nil) or
    (Castle.m_DoorStatus <> Door.Status) or
    (m_btRaceServer <> RC_PLAYOBJECT) or
    Castle.CheckInPalace(m_nCurrX, m_nCurrY, Self) then begin
    UserEngine.OpenDoor(m_PEnvir, nX, nY);
  end;
end;

//行会

procedure TPlayObject.ClientOpenGuildDlg;                                                           //004DE8E0
var
  i                                     : Integer;
  SC                                    : string;
begin

  if m_MyGuild <> nil then begin
    SC := TGuild(m_MyGuild).sGuildName + #13 + ' ' + #13;
    if m_nGuildRankNo = 1 then begin
      SC := SC + '1' + #13;
    end else begin
      SC := SC + '0' + #13;
    end;
    SC := SC + '<Notice>' + #13;
    for i := 0 to TGuild(m_MyGuild).NoticeList.Count - 1 do begin
      if Length(SC) > 5000 then Break;
      SC := SC + TGuild(m_MyGuild).NoticeList.Strings[i] + #13;
    end;                                                                                            // for
    SC := SC + '<KillGuilds>' + #13;
    for i := 0 to TGuild(m_MyGuild).m_GuildWarList.Count - 1 do begin
      if Length(SC) > 5000 then Break;
      SC := SC + TGuild(m_MyGuild).m_GuildWarList.Keys[i] + #13;
    end;                                                                                            // for
    SC := SC + '<AllyGuilds>' + #13;
    for i := 0 to TGuild(m_MyGuild).m_GuildAllList.Count - 1 do begin
      if Length(SC) > 5000 then Break;
      SC := SC + TGuild(m_MyGuild).m_GuildAllList.Keys[i] + #13;
    end;                                                                                            // for
    m_defMsg := MakeDefaultMsg(SM_OPENGUILDDLG, 0, 0, 0, 1);
    SendSocket(@m_defMsg, EnCodeString(SC));
  end else begin
    SendDefMessage(SM_OPENGUILDDLG_FAIL, 0, 0, 0, 0, '');
  end;
end;

procedure TPlayObject.ClientOpenHuanjing(nItemIdx: Integer; nOpCode: Integer; nCount: Integer);
var
  i, j                                  : Integer;
  Huanjing, UserItem                    : pTUserItem;
  StdItem                               : pTStdItem;
  tm                                    : DWORD;
  boFind                                : Boolean;
begin
  {点领取剩余奖励: Ident 34980 Param 0 P1 1073750150 P2 6 P3 0 Msg
   点注入10点:     Ident 34980 Param 0 P1 1073750150 P2 4 P3 10 Msg
   镶嵌蓝宝:nItemIdx: 1073750152(蓝宝ID); sItemName: ;nPackIdx: 1073750150(幻镜ID) }
  //找到幻镜:
  if (m_nHuanjingIdx <> 0) and (m_nHuanjingIdx <> nItemIdx) then Exit;
  Huanjing := nil;
  for i := 0 to m_ItemList.Count - 1 do begin
    if pTUserItem(m_ItemList[i]).MakeIndex = nItemIdx then begin
      Huanjing := pTUserItem(m_ItemList[i]);
      Break;
    end;
  end;
  if Huanjing = nil then Exit;

  case nOpCode of
    1: begin                                                                                        //双击打开
        if Huanjing.Dura > 0 then begin
          SendDefMessage(34980, nItemIdx, 513, 300, 3000, '');
          SendDefMessage(34980, nItemIdx, 769, 300, 3000, '');
          Exit;
        end else begin
          SendDefMessage(34980, nItemIdx, 513, 300, 3000, '');
          Exit;
        end;
      end;
    4: begin                                                                                        //注入灵力
        j := 0;
        for i := m_ItemList.Count - 1 downto 0 do begin
          UserItem := pTUserItem(m_ItemList[i]);
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if (StdItem <> nil) and (StdItem.StdMode = 3) and (StdItem.Shape in [202, 203]) then begin
            if StdItem.Shape = 202 then begin
              Dec(nCount);
              SendDelItems(UserItem);
              Dispose(UserItem);
              m_ItemList.Delete(i);
              WeightChanged;
              Inc(j);
            end else begin
              if UserItem.Dura >= nCount then begin                                                 //持久大于等于 数值
                Dec(UserItem.Dura, nCount);
                Inc(j, nCount);
                Dec(nCount, nCount);
              end else begin
                Inc(j, UserItem.Dura);
                Dec(nCount, UserItem.Dura);                                                         //增加点数
                UserItem.Dura := 0;
              end;
              if UserItem.Dura <= 0 then begin
                SendDelItems(UserItem);
                Dispose(UserItem);
                m_ItemList.Delete(i);
                WeightChanged;
              end else
                SendUpdateItem(UserItem);
            end;
            if nCount <= 0 then Break;
          end;
        end;

        Inc(Huanjing.Dura, j);
        if Huanjing.btValue[1] = 0 then begin                                                       //开启时间,也就是最后领奖时间
          tm := DateTimeToWolTIme(Now);
          Huanjing.btValue[2] := LoByte(LoWord(tm));
          Huanjing.btValue[3] := HiByte(LoWord(tm));
          Huanjing.btValue[4] := LoByte(HiWord(tm));
          Huanjing.btValue[5] := HiByte(HiWord(tm));
        end;

        m_nHuanjingIdx := nItemIdx;
        m_dwHuanjingTick := GetTickCount;
        SendUpdateItem(Huanjing);
        SendDefMessage(34980, nItemIdx, 769, 300, 3000, '');
        SysMsg('你已成功为天关幻镜注入了' + IntToStr(j) + '个灵符的灵力', c_Red, t_Hint);
        if nCount = 0 then begin
          SysMsg('灵符的灵力使幻镜映射出无穷的宝藏,但如果灵力耗尽幻镜就会立刻碎裂', c_Red, t_Hint);
        end;
      end;
    6: begin
        if (Huanjing.Dura = 0) or ((Huanjing.btValue[1] = 1) and
          (Huanjing.btValue[6] = 1)) then begin                                                     //破碎后还可以领一次
          SysMsg('天关幻镜中没有累积的奖励可以领取', c_Red, t_Hint);
          Exit;
        end;
        //检查时间间隔
        tm := MakeLong(MakeWord(Huanjing.btValue[2], Huanjing.btValue[3]),
          MakeWord(Huanjing.btValue[4], Huanjing.btValue[5]));
        if tm + g_Config.nHuanjingGetGift <= DateTimeToWolTIme(Now) then begin
          if g_FunctionNPC <> nil then begin
            if tm = 0 then
              m_sScriptParam[0] := '1'
            else
              m_sScriptParam[0] := IntToStr((DateTimeToWolTIme(Now) - tm + 1) div
                g_Config.nHuanjingGetGift);
            m_sScriptParam[1] := IntToStr(Huanjing.Dura);                                           //幻境灵力
            m_sScriptParam[2] := IntToStr(Huanjing.btValue[1]);
            //幻境状态 0正常 1破碎
            m_sScriptParam[3] := m_PEnvir.m_sMapName;                                               //地图名
            m_sScriptParam[4] := IntToStr(Huanjing.btValue[0]);
            //幻境镶嵌宝石类型  1 2 3 表示   0普通幻境
            m_sScriptParam[5] := IntToStr(Huanjing.MakeIndex);                                      //幻境ID
            ExecuteScript(g_FunctionNPC, '@天关幻镜奖励');
            tm := DateTimeToWolTIme(Now);
            Huanjing.btValue[2] := LoByte(LoWord(tm));
            Huanjing.btValue[3] := HiByte(LoWord(tm));
            Huanjing.btValue[4] := LoByte(HiWord(tm));
            Huanjing.btValue[5] := HiByte(HiWord(tm));
            if (Huanjing.btValue[1] = 1) and (Huanjing.btValue[6] = 0) then
              Huanjing.btValue[6] := 1;
          end;
        end else begin
          SysMsg('无法连续领取天关幻镜中奖励,请过会再来领取', c_Red, t_Hint);
{$IF USESDK = DEBUG}
          SysMsg('上次时间:' + IntToStr(tm) + ',当前时间:' + IntToStr(DateTimeToWolTIme(Now)), c_Red, t_Hint);
{$IFEND}
        end;
      end;
    260: begin
        if m_nGameGold >= nCount then begin
          Inc(Huanjing.Dura, nCount);
          if Huanjing.btValue[1] = 0 then begin                                                     //开启时间,也就是最后领奖时间
            tm := DateTimeToWolTIme(Now);
            Huanjing.btValue[2] := LoByte(LoWord(tm));
            Huanjing.btValue[3] := HiByte(LoWord(tm));
            Huanjing.btValue[4] := LoByte(HiWord(tm));
            Huanjing.btValue[5] := HiByte(HiWord(tm));
          end;
          SendUpdateItem(Huanjing);
          //SendDefMessage(34980, nItemIdx, 513, 300, 3000, '');
          SendDefMessage(34980, nItemIdx, 769, 300, 3000, '');
          SysMsg('你已成功为天关幻镜注入了' + IntToStr(nCount) + '个灵符的灵力', c_Red, t_Hint);
          SysMsg('灵符的灵力使幻镜映射出无穷的宝藏,但如果灵力耗尽幻镜就会立刻碎裂', c_Red, t_Hint);
          Dec(m_nGameGold, nCount);                                                                 //元宝减少
          Inc(m_nGamePoint, nCount);                                                                //积分增加
          GameGoldChanged;
          m_nHuanjingIdx := nItemIdx;
          m_dwHuanjingTick := GetTickCount;
        end;
      end;
  end;
end;

function TPlayObject.ClientOpPneumaBagItem(sData: string): Boolean;
var
  OpInfo                                : TPneumaItem;
  UserItem                              : pTUserItem;
  i, ii                                 : Integer;
  StdItem                               : pTStdItem;
resourcestring
  sHint1                                = '宝盒物品不能给元神分身';
  sHint2                                = '该物品不能放入元神分身的包裹';
  sHint3                                = '元神分身包裹里的东西太多或者负重不够';
  sHint4                                = '玩家包裹里的东西太多或者负重不够';
begin
  Result := False;
  if sData = '' then Exit;
  if m_boGhost or m_boDeath then Exit;
  if (m_PneumaObject = nil) or m_PneumaObject.m_boGhost or
    m_PneumaObject.m_boDeath then Exit;

  DeCodeBuffer(sData, @OpInfo, SizeOf(TPneumaItem));
  if Integer(m_PneumaObject) <> OpInfo.nChrID then Exit;

  if (OpInfo.btFlag = 1) then begin                                                                 //移动物品到元神包裹
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := m_ItemList.Items[i];
      if (UserItem <> nil) and (UserItem.MakeIndex = OpInfo.nMakeIndex) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem = nil then Break;
        {物品控制-禁止放入元神包裹}
        if CheckSPCode(StdItem.SPCode, SP_DISABLEINPNEUMABAG) then begin
          SysMsg(sHint2, c_Red, t_Hint);
          Break;
        end;

        {已放出豹禁止放入元神包裹}
        if IsDownPetItem(UserItem.MakeIndex) then begin
          Break;
        end;

        if TPlayObject(m_PneumaObject).IsEnoughBag and
          TPlayObject(m_PneumaObject).IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex)) then begin
          m_ItemList.Delete(i);
          SendDelItems(UserItem);
          m_PneumaObject.m_ItemList.Add(UserItem);
          TPlayObject(m_PneumaObject).SendAddItem(UserItem);
          Result := True;
          WeightChanged();
          TPlayObject(m_PneumaObject).WeightChanged;
        end else begin
          SysMsg(sHint3, c_Red, t_Hint);
        end;
        Break;
      end;
    end;
  end else if (OpInfo.btFlag = 0) then begin                                                        //元神包裹中的物品移动到人物
    for i := m_PneumaObject.m_ItemList.Count - 1 downto 0 do begin
      UserItem := m_PneumaObject.m_ItemList.Items[i];
      if (UserItem <> nil) and (UserItem.MakeIndex = OpInfo.nMakeIndex) then begin
        if IsEnoughBag and
          IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex)) then begin
          m_PneumaObject.m_ItemList.Delete(i);
          TPlayObject(m_PneumaObject).SendDelItems(UserItem);
          m_ItemList.Add(UserItem);
          SendAddItem(UserItem);
          Result := True;
          WeightChanged();
          TPlayObject(m_PneumaObject).WeightChanged;
        end else begin
          SysMsg(sHint4, c_Red, t_Hint);
        end;
        Break;
      end;
    end;
  end;

  if Result then
    OpInfo.btOpCode := 1
  else
    OpInfo.btOpCode := 0;
  m_defMsg := MakeDefaultMsg(SM_9608, Integer(Self), 0, 0, 0);
  SendSocket(@m_defMsg, EnCodeBuffer(@OpInfo, SizeOf(TPneumaItem)));

  //  UserEngine.SaveHumanRcd(Self);
  //  UserEngine.SaveHumanRcd(TPlayObject(m_PneumaObject));
end;

function TPlayObject.ClientOpPneumaGold(sData: string): Boolean;
var
  OpInfo                                : TPneumaItem;
resourcestring
  sHint1                                = '你没有这么多钱';
  sHint2                                = '你的分身没有这么多钱';
begin
  Result := False;
  if sData = '' then Exit;
  if m_boGhost or m_boDeath then Exit;
  if (m_PneumaObject = nil) or m_PneumaObject.m_boGhost or
    m_PneumaObject.m_boDeath then Exit;

  DeCodeBuffer(sData, @OpInfo, SizeOf(TPneumaItem));
  if (Integer(m_PneumaObject) <> OpInfo.nChrID) or (OpInfo.nMakeIndex <= 0) then
    Exit;

  if (OpInfo.btFlag = 1) then begin                                                                 //移动金币到元神包裹
    if OpInfo.nMakeIndex <= m_nGold then begin
      if TPlayObject(m_PneumaObject).IncGold(OpInfo.nMakeIndex) then begin
        TPlayObject(m_PneumaObject).GoldChanged;
        DecGold(OpInfo.nMakeIndex);
        GoldChanged;
        Result := True;
      end else
        TPlayObject(m_PneumaObject).SysMsg(g_sYourGoldLargeThenLimit, c_Red, t_Hint);
    end else
      SysMsg(sHint1, c_Red, t_Hint);
  end else if (OpInfo.btFlag = 0) then begin                                                        //元神包裹中的金币移动到人物
    if OpInfo.nMakeIndex <= TPlayObject(m_PneumaObject).m_nGold then begin
      if IncGold(OpInfo.nMakeIndex) then begin
        GoldChanged;
        TPlayObject(m_PneumaObject).DecGold(OpInfo.nMakeIndex);
        TPlayObject(m_PneumaObject).GoldChanged;
        Result := True;
      end else
        SysMsg(g_sYourGoldLargeThenLimit, c_Red, t_Hint);
    end else
      SysMsg(sHint2, c_Red, t_Hint);
  end;
end;

procedure TPlayObject.ClientPersonalSet(Parm1, Parm2, Parm3: Word; sMsg: string);
var
  StyleConfig                           : TConfigStyle;
resourcestring
  sHint                                 = '1分钟内只能设置一次';
  sOK                                   = '设置成功';
begin
  if GetTickCount < m_dwLastPersonalSetTick + 60 * 1000 then begin
    SysMsg(sHint, c_Red, t_Hint);
  end else begin
    m_dwLastPersonalSetTick := GetTickCount;
    DeCodeBuffer(sMsg, @StyleConfig, SizeOf(TConfigStyle));
    m_sTmpRank := StyleConfig.chTempRank;
    m_sPersonalSign := StyleConfig.chStyleName;                                                     //UserEngine.m_PersonSignIni.WriteString(m_sCharName, 'Sign', m_sPersonalSign);
    //参数3是几个选择项
    m_wPersonalCode := Parm1;

    SysMsg(sOK, c_Green, t_Hint);
    SendDefMessage(SM_PERSONALSIGN, Integer(Self), 1, 0, m_wPersonalCode, m_sPersonalSign);
    SendDefMessage(SM_PERSONALSIGN, Integer(Self), 3, 1, 0, '');
    if m_sTmpRank <> '' then SendDefMessage(SM_PERSONALSIGN, Integer(Self), 2, 0, 0, m_sTmpRank);
    RefShowName;
    FeatureChanged;
    m_sScriptParam[0] := m_sTmpRank;
    ExecuteScript(g_ManageNpc, '@封号_个性设置');
  end;
end;

//凤凰探宝

procedure TPlayObject.ClientPhoenixSearch(nPetItem, nParm2: Integer);
var
  tm, tm1                               : LongWord;
  UserItem                              : pTUserItem;
begin
  GetUserItemByMakeIndex(nPetItem, UserItem);
  if UserItem = nil then Exit;

  m_sScriptParam[0] := IntToStr(nPetItem);
  case nParm2 of
    0: begin                                                                                        //探宝
        if (m_Pet = nil) then Exit;
        if m_PetInfo[0].nMakeIndex <> nPetItem then Exit;
        m_Pet.SendRefMsg(RM_510, 1, 0, 108, 0, '');                                                 //凤凰消失

        m_PetInfo[4] := m_PetInfo[0];
        PetHide(m_PetInfo[0].nMakeIndex);

        SendPetInfo($09);
        //记录探宝的时间
        tm := DateTimeToWolTIme(Now);
        UserItem.btItemExt[6] := LoByte(LoWord(tm));
        UserItem.btItemExt[7] := HiByte(LoWord(tm));
        UserItem.btItemExt[8] := LoByte(HiWord(tm));
        UserItem.btItemExt[9] := HiByte(HiWord(tm));
        ExecuteScript(g_ManageNPC, '@凤凰探宝');
      end;
    1: begin                                                                                        //召唤   - 计算探宝的时间
        //检查时间间隔
        tm := MakeLong(MakeWord(UserItem.btItemExt[6], UserItem.btItemExt[7]), MakeWord(UserItem.btItemExt[8], UserItem.btItemExt[9]));
        tm1 := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        tm1 := tm1 + 86400 * 4;                                                                     //饥饿
        tm := _MIN(DateTimeToWolTIme(Now), tm1) - tm;                                               //取最小的时间间隔
        UserItem.btItemExt[6] := LoByte(LoWord(tm));
        UserItem.btItemExt[7] := HiByte(LoWord(tm));
        UserItem.btItemExt[8] := LoByte(HiWord(tm));
        UserItem.btItemExt[9] := HiByte(HiWord(tm));
        //刷新石头状态
        m_defMsg := MakeDefaultMsg(34977, 0, 100, 0, 0);
        SendSocket(@m_defMsg, EnCodeBuffer(@nPetItem, 4));
        m_PetInfo[4].nMakeIndex := 0;
        m_PetInfo[4].wLevel := 0;
        m_PetInfo[4].btType := 0;
        m_PetInfo[4].btReLive := 0;
      end;
    2: begin                                                                                        //领宝
        //检查时间间隔
        tm := MakeLong(MakeWord(UserItem.btItemExt[12], UserItem.btItemExt[13]), MakeWord(UserItem.btItemExt[14], UserItem.btItemExt[15]));
        if tm + g_Config.nPhoenixGetGift <= DateTimeToWolTIme(Now) then begin
          if g_ManageNPC <> nil then begin
            //获取探宝时间秒数
            tm := MakeLong(MakeWord(UserItem.btItemExt[6], UserItem.btItemExt[7]), MakeWord(UserItem.btItemExt[8], UserItem.btItemExt[9]));
            m_sScriptParam[1] := IntToStr(tm div 60);                                               //返回分钟
            ExecuteScript(g_ManageNPC, '@凤凰领宝');
            tm := DateTimeToWolTIme(Now);
            UserItem.btItemExt[12] := LoByte(LoWord(tm));
            UserItem.btItemExt[13] := HiByte(LoWord(tm));
            UserItem.btItemExt[14] := LoByte(HiWord(tm));
            UserItem.btItemExt[15] := HiByte(HiWord(tm));
          end;
        end else begin
          SysMsg('无法连续领取凤凰探宝的奖励,请过会再来领取', c_Red, t_Hint);
{$IF USESDK = DEBUG}
          SysMsg('上次时间:' + IntToStr(tm) + ',当前时间:' + IntToStr(DateTimeToWolTIme(Now)), c_Red, t_Hint);
{$IFEND}
        end;
      end;
  end;
end;

function TPlayObject.ClientPickUpItem(nX, nY, nType: Integer): Boolean;
//捡物品

  function IsSelf(BaseObject: TBaseObject): Boolean;
  begin
    Result := (BaseObject = nil) or (Self = BaseObject) or (BaseObject.m_Master = Self) or (BaseObject.m_PneumaObject = Self);
  end;

  function IsOfGroup(BaseObject: TBaseObject): Boolean;
  var
    i                                   : Integer;
    GroupMember, ItemOfCreat            : TBaseObject;
  begin
    Result := False;
    //如果是元神
    if (m_btRaceServer = RC_PLAYOBJECT) and m_boPneuma and (m_PneumaObject <> nil) then begin
      m_GroupOwner := m_PneumaObject.m_GroupOwner;
    end;

    ItemOfCreat := BaseObject;
    if (BaseObject <> nil) and (BaseObject.m_btRaceServer = RC_PLAYOBJECT) and (BaseObject.m_boPneuma) and (BaseObject.m_PneumaObject <> nil) then begin
      ItemOfCreat := BaseObject.m_PneumaObject;
    end;

    if m_GroupOwner = nil then Exit;
    for i := 0 to m_GroupOwner.m_GroupMembers.Count - 1 do begin
      GroupMember := TBaseObject(m_GroupOwner.m_GroupMembers.Objects[i]);
      if GroupMember = ItemOfCreat then begin
        Result := True;
        Break;
      end;
    end;
  end;
var
  UserItem                              : pTUserItem;
  MapItem                               : pTMapItem;
  StdItem                               : pTStdItem;
resourcestring
  sHint1                                = '上古神魔的力量慢慢弱去,你的身体恢复正常。';
  sHint2                                = '来自上古的神魔赐予了你一股神奇的力量';
  sHint3                                = '你获得了秒杀的神力';
  sHint4                                = '被激发的神魔秒杀结界,将帮助你杀怪物时的攻击力大增';
  sHint5                                = '神力将持续%d分钟……';
  sHint6                                = '你获得了重击的神力';
  sHint7                                = '被激发的神魔重击结界,将帮助你有机会秒杀怪物';
  sHint8                                = '你获得了神御的神力';
  sHint9                                = '被激发的神魔防御结界,将帮助你抵御怪物的攻击';
  sHint10                               = '你获得了神佑的神力';
  sHint11                               = '神魔的眷顾可能让你在%d分钟内获得双倍的经验';
  sHint12                               = '进入炼狱更有可能获得三倍……';
begin
  Result := False;
  if m_boPneuma and (m_boPneumaEffMode) then Exit;                                                  //灵珠状态不能拾取物品
  if m_boDealing or (m_wShopItemCount > 0) then Exit;

  MapItem := m_PEnvir.GetItem(nX, nY);
  if MapItem = nil then Exit;

  //物品在2分钟之内不允许其他人捡
  if (GetTickCount - MapItem.dwCanPickUpTick) > g_Config.dwFloorItemCanPickUpTime {2 * 60 * 1000} then begin
    MapItem.OfBaseObject := nil;
  end;

  //宝物在冻结状态下不能拾取,请耐心等待冻结时间消失
  if (MapItem.OfBaseObject = g_FunctionNPC) then begin
    if (m_btRaceServer = RC_PLAYOBJECT) then
      SysMsg(g_sCanPickUpItemByFreeze {'宝物在冻结状态下不能拾取,请耐心等待冻结时间消失!'}, c_Red, t_Hint);
    Exit;
  end;

  //检查物品的主人
  if not IsSelf(TBaseObject(MapItem.OfBaseObject)) and not IsOfGroup(TBaseObject(MapItem.OfBaseObject)) then begin
    if (m_btRaceServer = RC_PLAYOBJECT) then
      SysMsg(g_sCanotPickUpItem {'在一定时间以内无法捡起此物品!!!'}, c_Red, t_Hint);
    Exit;
  end;

  //脚本参数入口
  m_sScriptParam[21] := IntToStr(MapItem.UserItem.MakeIndex);
  m_sScriptParam[22] := MapItem.Name;
  m_sScriptParam[23] := IntToStr(MapItem.btDropBaseRace);
  m_sScriptParam[24] := MapItem.sDropBaseNams;
  m_sScriptParam[25] := IntToStr(nType);                                                            //是否豹子拾取
  //捡金币
  if CompareText(MapItem.Name, sSTRING_GOLDNAME) = 0 then begin
    if m_PEnvir.DeleteFromMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem)) = 1 then begin
      if IncGold(MapItem.Count) then begin
        SendRefMsg(RM_ITEMHIDE, 0, Integer(MapItem), nX, nY, '');                                   //物品消失
        if g_boGameLogGold then
          AddGameDataLog('4' + #9 +
            m_sMapName + #9 +
            IntToStr(nX) + #9 +
            IntToStr(nY) + #9 +
            m_sCharName + #9 +
            sSTRING_GOLDNAME + #9 +
            IntToStr(MapItem.Count) + #9 +
            '1' + #9 +
            '0');
        GoldChanged;
        Dispose(MapItem);
      end else
        m_PEnvir.AddToMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem));
    end;
    if g_Config.boStartMapEvent and (m_btRaceServer = RC_PLAYOBJECT) then begin
      StartMapEventOfPickUpItem(sSTRING_GOLDNAME);
    end;
    Exit;
  end;
  //绑定金币
  if CompareText(MapItem.Name, sSTRING_BINDGOLDNAME) = 0 then begin
    if m_PEnvir.DeleteFromMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem)) = 1 then begin
      if IncBindGold(MapItem.Count) then begin
        SendRefMsg(RM_ITEMHIDE, 0, Integer(MapItem), nX, nY, '');                                   //物品消失
        if g_boGameLogGold then
          AddGameDataLog('4' + #9 +
            m_sMapName + #9 +
            IntToStr(nX) + #9 +
            IntToStr(nY) + #9 +
            m_sCharName + #9 +
            sSTRING_BINDGOLDNAME + #9 +
            IntToStr(MapItem.Count) + #9 +
            '1' + #9 +
            '0');
        GoldChanged(1);
        Dispose(MapItem);
      end else
        m_PEnvir.AddToMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem));
    end;
    if g_Config.boStartMapEvent and (m_btRaceServer = RC_PLAYOBJECT) then begin
      StartMapEventOfPickUpItem(sSTRING_BINDGOLDNAME);
    end;
    Exit;
  end;

  //捡到附身物品
  StdItem := UserEngine.GetStdItem(MapItem.UserItem.wIndex);
  if (StdItem <> nil) then begin
    if (StdItem.StdMode = 57) and (m_btRaceServer = RC_PLAYOBJECT) and (nType = 0) then begin
      if m_PEnvir.DeleteFromMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem)) = 1 then begin
        if m_wFushen > 0 then
          SysMsg(sHint1, c_Red, t_Hint);
        m_wFushen := StdItem.Shape;
        m_dwFushenTime := StdItem.AniCount * 60000;
        m_dwFushenTick := GetTickCount;
        m_nMagicStatus := GetMagicStatus();
        Status2Changed();
        SysMsg(sHint2, c_Red, t_Hint);
        case StdItem.Shape of
          1: begin
              SysMsg(sHint3, c_Red, t_Hint);
              SysMsg(sHint4, c_Red, t_Hint);
              SysMsg(Format(sHint5, [StdItem.AniCount]), c_Red, t_Hint);
            end;
          2: begin
              SysMsg(sHint6, c_Red, t_Hint);
              SysMsg(sHint7, c_Red, t_Hint);
              SysMsg(Format(sHint5, [StdItem.AniCount]), c_Red, t_Hint);
            end;
          3: begin
              SysMsg(sHint8, c_Red, t_Hint);
              SysMsg(sHint9, c_Red, t_Hint);
              SysMsg(Format(sHint5, [StdItem.AniCount]), c_Red, t_Hint);
            end;
          4: begin
              SysMsg(sHint10, c_Red, t_Hint);
              SysMsg(Format(sHint11, [StdItem.AniCount]), c_Red, t_Hint);
              SysMsg(sHint12, c_Red, t_Hint);
            end;
        end;
        SendMsg(Self, RM_ITEMHIDE, 0, Integer(MapItem), nX, nY, '');
        Dispose(MapItem);
        Result := True;
      end;

      if g_Config.boStartMapEvent then begin
        StartMapEventOfPickUpItem(StdItem.Name);
      end;
      Exit;
    end;

    //禁止包裹重复
    if CheckSPCode(StdItem.SPCode, SP_DISABLEDUPLICATE) then begin
      if GetUserItemByIdx(MapItem.UserItem.wIndex, UserItem) <> -1 then begin
        if (m_btRaceServer = RC_PLAYOBJECT) then
          SysMsg(Format(g_sCanPickUpItemDuplicate {'你只能同时拥有一个%s'}, [StdItem.FilterName]), c_Red, t_Hint);
        Exit;
      end;
    end;

    if m_boPneuma and CheckSPCode(StdItem.SPCode, SP_DISABLEINPNEUMABAG) then Exit;                 //禁止元神捡取

    if (nType = 1) and CheckSPCode(StdItem.SPCode, SP_DISABLEINPETBAG) then Exit;                   //禁止宠物捡取
    if (nType = 1) and (m_PetInfo[0].btType < 6) and (m_PetInfo[0].wLevel < 2) then Exit;           //1级丛林豹不允许捡物品

    //龙凤绣球-禁止已婚或者女性捡取
    if ((StdItem.StdMode = 50) and (StdItem.Looks = 513)) and
      ((m_sDearName <> '') or (m_btGender = 1)) then Exit;

    //宝盒系统控制-骑马禁止捡取宝盒
    if m_boRideOn and CheckSPCode(StdItem.Reserved, RE_TREASURE) then begin
      Exit;
    end;
    //不是金币或附身,则放到包裹里
    if IsEnoughBag then begin
      if m_PEnvir.DeleteFromMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem)) = 1 then begin
        New(UserItem);
        UserItem^ := MapItem.UserItem;
        if IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex)) then begin
          SendMsg(Self, RM_ITEMHIDE, 0, Integer(MapItem), nX, nY, '');
          //物品消失
          AddItemToBag(UserItem);

          if StdItem.boGameLog = 1 then
            AddGameDataLog('4' + #9 +
              m_sMapName + #9 +
              IntToStr(nX) + #9 +
              IntToStr(nY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              '0');
          Dispose(MapItem);

          if m_btRaceServer = RC_PLAYOBJECT then begin
            SendAddItem(UserItem);

            //捡取触发
            if (g_FunctionNPC <> nil) then begin
              ExecuteScript(g_FunctionNPC, '@拾取物品');
            end;

            if (g_FunctionNPC <> nil) and (not m_boPneuma) then begin
              ExecuteScript(g_FunctionNPC, '@PickUpItem' + IntToStr(StdItem.AniCount));
            end;

            if g_Config.boStartMapEvent then begin
              StartMapEventOfPickUpItem(StdItem.Name);
            end;
          end;
          Result := True;
        end else begin
          Result := False;
          Dispose(UserItem);
          m_PEnvir.AddToMap(nX, nY, OS_ITEMOBJECT, TObject(MapItem));
        end;
      end;
    end;
  end;

  if not Result then SysMsg(g_sBagIsFullOrWearWeightNot, c_Red, t_Hint);
end;

procedure TPlayObject.ClientQueryBaoshi;
var
  i                                     : Integer;
  ItemCount                             : array[0..2] of Integer;
  sItemName                             : string;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  ItemCount[0] := m_wGemCount[0];
  ItemCount[1] := m_wGemCount[1];
  ItemCount[2] := m_wGemCount[2];
  m_SMELTNPC := m_ClickNPC;                                                                         //记录当前NPC
  SendDefMessage(SM_BAOSHI, Integer(Self), MakeWord(ItemCount[0], ItemCount[1]), ItemCount[2], 0, '');
end;

procedure TPlayObject.ClientQueryEvilFollower;
var
  i, nCount                             : Integer;
  Slave                                 : TBaseObject;
  EvilData                              : TEvilData;
begin
  nCount := 0;
  FillChar(EvilData, SizeOf(TEvilData), #0);
  EvilData.dw1 := m_nEvilFollowerPowerMax;
  EvilData.dw2 := 3500;
  for i := 0 to m_SlaveList.Count - 1 do begin
    if nCount > 4 then Break;
    Slave := TBaseObject(m_SlaveList[i]);
    if Slave.m_boDeath or Slave.m_boGhost or (Slave.m_btRaceServer <> RC_EVIL) then Continue;
    EvilData.Evil[i].dwEvilID := Integer(Slave);
    EvilData.Evil[i].btLevel := Slave.m_wSlaveExpLevel;
    case Slave.m_btAmbitLevel of
      0: EvilData.Evil[i].btAmbit := 0;
      1..3: EvilData.Evil[i].btAmbit := 1;
      4..6: EvilData.Evil[i].btAmbit := 2;
      7..9: EvilData.Evil[i].btAmbit := 3;
      10: EvilData.Evil[i].btAmbit := 4;
    end;
    EvilData.Evil[i].btJob := Slave.m_btJob;
    Inc(nCount);
  end;
  m_defMsg := MakeDefaultMsg(CM_RECALLEVIL, 0, MakeWord(1, nCount),
    m_nEvilFollowerPower, 0);
  SendSocket(@m_defMsg, EnCodeBuffer(@EvilData, SizeOf(TEvilData)));
end;

procedure TPlayObject.ClientQueryMapLotusInfo();
var
  i                                     : Integer;
  pLotusInfo                            : pTLotusInfo;
begin
  g_LotusInfoList.Lock;
  try
    for i := 0 to g_LotusInfoList.Count - 1 do begin
      pLotusInfo := g_LotusInfoList.Items[i];
      if (CompareText(pLotusInfo^.sMapName, m_sMapName) = 0) then begin
        SendDefMessage(SM_LOTUSINFO,
          MakeWord(pLotusInfo^.btType, pLotusInfo^.btStatus),
          pLotusInfo^.nX,
          pLotusInfo^.nY,
          0,
          pLotusInfo^.sChrName + '/' + pLotusInfo^.sMapName);
      end;
    end;
  finally
    g_LotusInfoList.UnLock;
  end;
end;

procedure TPlayObject.ClientQueryRepairCost(nParam1, nInt: Integer; nRepairType:
  Integer; sMsg: string);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  UserItemA                             : pTUserItem;
  Merchant                              : TMerchant;
  sName, sTmp                           : string;
  StdItem                               : pTStdItem;
  sSendMsg                              : string;
begin
  UserItemA := nil;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if (UserItem.MakeIndex = nInt) then begin
      {取自定义物品名称}
      sName := '';
      ItemUnit.GetCustomItemName(UserItem, sName);

      if (CompareText(sMsg, sName) = 0) then begin
        UserItemA := UserItem;
        Break;
      end;
    end;
  end;
  if UserItemA = nil then begin
    SendDefMessage(618, nInt, 1, 0, 0, '');
    Exit;
  end;
  if nParam1 <= 1 then begin
    StdItem := UserEngine.GetStdItem(UserItemA.wIndex);
    if (StdItem.StdMode in [5, 6, 10, 11, 15, 19..24, 26, 30, 58, 81]) and
      (nRepairType = 3) and (UserItemA.btItemExt[4] = 4) then
    begin
      sSendMsg := Format('您的%s已经破碎了,运用%d点五色晶石的力量就可将其修复如新,您愿意修复吗?', [StdItem.Name, StdItem.Broken]);
      m_sNextLabel := Format('Fracture:%d', [UserItemA.MakeIndex]);
      SendDefMessage(SM_MENU_OKCANCEL, Integer(Self), 0, 0, 1, sSendMsg);
    end;
  end;
  Merchant := UserEngine.FindMerchant(TObject(nParam1));
  if (Merchant <> nil) and
    (IsEnvir(Merchant.m_PEnvir) and
    (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
    (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) then
    Merchant.ClientQueryRepairCost(Self, UserItemA, nRepairType);
end;

//查看宝宝列表

procedure TPlayObject.ClientQuerySlaverState;
var
  i                                     : Integer;
  SlaveInfo                             : TViewSlaveInfo;
  SlaveInfoList                         : array[0..9] of TViewSlaveInfo;
  Slave                                 : TBaseObject;
  s1C                                   : string;
  SlaveCount                            : Integer;
  sName                                 : string;
begin
  SlaveCount := 0;
  for i := 0 to m_SlaveList.Count - 1 do begin
    if SlaveCount > 4 then Break;
    Slave := TBaseObject(m_SlaveList[i]);
    if Slave.m_boDeath or Slave.m_boGhost or (Slave = m_Horse) or Slave.m_boIsPet or
      Slave.m_boGodCallBoss or Slave.m_boScapeGoat or (Slave.m_nSlaveType = -2) then Continue;

    FillChar(SlaveInfo, SizeOf(TViewSlaveInfo), 0);
    SlaveInfo.level := Slave.m_wSlaveExpLevel;
    StrPLCopy(SlaveInfo.Name, Slave.m_sFilterCharName, 14);
    if (Slave.m_btRaceServer = RC_EVIL) then begin
      SlaveInfo.HP := m_nEvilFollowerPower div 500;
      SlaveInfo.MaxHP := m_nEvilFollowerPowerMax div 500;
    end else begin
      SlaveInfo.HP := Slave.m_WAbil.dwHP;
      SlaveInfo.MaxHP := Slave.m_WAbil.dwMaxHP;
    end;
    SlaveInfo.DC := MakeLong(loword(Slave.m_WAbil.DC), hiword(Slave.m_WAbil.DC));
    SlaveInfo.AC := hiword(Slave.m_WAbil.AC);
    SlaveInfo.MAC := hiword(Slave.m_WAbil.MAC);
    SlaveInfo.C := '/';
    SlaveInfoList[SlaveCount] := SlaveInfo;

    Inc(SlaveCount);
  end;

  if SlaveCount > 0 then begin
    s1C := EnCodeBuffer(@SlaveInfoList, SizeOf(TViewSlaveInfo) * SlaveCount);
    m_defMsg := MakeDefaultMsg(SM_QUERYSLAVER, 0, 0, 0, 0);
    SendSocket(@m_defMsg, s1C);
  end;
end;

procedure TPlayObject.ClientQueryTreasureBoxItems(const boSend: Boolean = True);
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnQueryTreasureBoxItems(Self, boSend);
  except
    MainOutMessage(Format('TPlayObject::OnQueryTreasureBoxItems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//查询用户名

procedure TPlayObject.ClientQueryUserName(Target: TBaseObject; X, Y: Integer);
var
  uname                                 : string;
  TagColor                              : Integer;
  Def                                   : TDefaultMessage;
  i                                     : Integer;
begin
  if CretInNearXY(Target, X, Y) then begin
    TagColor := GetCharColor(Target);
    Def := MakeDefaultMsg(SM_USERNAME, Integer(Target), TagColor, 0, 0);
    uname := Target.GetShowName;
    SendSocket(@Def, EnCodeString(uname));
  end else begin
    Def := MakeDefaultMsg(SM_GHOST, Integer(Target), X, Y, 0);
    i := 0;
    SendSocket(@Def, EnCodeBuffer(@i, SizeOf(Integer)));
  end;
end;
//召唤封元守卫

procedure TPlayObject.ClientReCallGuarder(nMakeIndex, nX, nY: Integer);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  boEatOK                               : Boolean;
begin
  boEatOK := False;
  if GetUserItemByMakeIndex(nMakeIndex, UserItem) >= 0 then begin
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (StdItem <> nil) then begin
      if (StdItem.StdMode = 49) and (StdItem.Shape = 55) then begin
        //封元神力不足
        if (m_btFengYuanPoint < 2) then begin
          SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
          SendDefMessage(3046, 0, 0, 0, 11, '');
          SysMsg('封印神力不足,无法召唤此怪物,请在下轮防守时再召唤', c_Red, t_Hint);
          Exit;
        end;

        if (StdItem.Looks = 5050) then begin
          if ((nX = 19) and (nY = 28)) or ((nX = 23) and (nY = 32)) or
            ((nX = 27) and (nY = 36)) or ((nX = 31) and (nY = 40)) or
            ((nX = 27) and (nY = 44)) or ((nX = 23) and (nY = 48)) then
            boEatOK := True
          else
            SendDefMessage(3046, 0, 0, 0, 10, '');
        end else
          boEatOK := True;

        if boEatOK then begin
          m_sScriptParam[0] := IntToStr(nMakeIndex);
          m_sScriptParam[1] := IntToStr(nX);
          m_sScriptParam[2] := IntToStr(nY);
          boEatOK := ExecuteScript(g_ManageNPC, '@释放封元印');
        end;

        if boEatOK then
          SendDefMessage(3046, 0, nX, nY, 6, '')
        else
          SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
      end;
    end;
  end;
end;

procedure TPlayObject.ClientReCallTiger();
var
  i                                     : Integer;
begin
  if m_boGhost or m_boDeath then Exit;
  if (m_Tiger <> nil) then begin
    //删除宠物
    for i := m_SlaveList.Count - 1 downto 0 do begin
      if m_SlaveList[i] = m_Tiger then begin
        m_SlaveList.Delete(i);
        Break;
      end;
    end;
    if (m_Tiger <> nil) and (not m_Tiger.m_boDeath) and (not m_Tiger.m_boGhost) then
      m_Tiger.KickException;
    m_Tiger := nil;
  end;
  SendDefMessage(CM_CALLTIGER, 0, 2, 0, 0, '');
end;

//合成魂骨

procedure TPlayObject.ClientEntopticSmelt(nState: Integer; sData: string);
var
  buf                                   : array[0..5] of Integer;
  i, j                                  : Integer;
  nCode                                 : Integer;
  ANpc                                  : TNormNpc;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  pUserItems                            : array[0..5] of pTUserItem;
  pStdItems                             : array[0..5] of pTStdItem;
  sMsg, sLable                          : string;
  sLableOK                              : string;
begin
  for i := 0 to 5 do begin
    m_sScriptParam[i] := '';
    pUserItems[i] := nil;
    pStdItems[i] := nil;
    buf[i] := 0;
  end;
  sLable := '';
  sLableOK := '';

  if m_ClickNPC = nil then Exit;
  ANpc := TNormNpc(m_ClickNPC);
  DeCodeBuffer(sData, @buf[0], SizeOf(Integer) * 6);
  nCode := 0;
  for i := 0 to 5 do begin
    for j := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[j];
      if UserItem.MakeIndex = buf[i] then begin
        pUserItems[i] := UserItem;
        pStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
        Break;
      end;
    end;
    if ((pUserItems[i] = nil) or (pStdItems[i] = nil)) then begin
      nCode := -1;
      sMsg := '你所要魂骨没有在你的包裹里发现';
      Break;
    end;
  end;
  {函数标签初始}
  sLable := '@@BoneCompound';
  {函数触发开始}
  if (nCode = 0) then begin
    for i := 0 to 5 do begin
      if pUserItems[i] <> nil then begin
        m_sScriptParam[i] := IntToStr(pUserItems[i].MakeIndex);
{$IF USESDK = DEBUG}
        SysMsg(Format('物品%d:%d', [i, pUserItems[i].MakeIndex]), c_Pink, t_Hint);
{$IFEND}
      end;
    end;
    if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
      if (sLable <> '') then ANpc.GotoLable(Self, sLable, False);
    end;
  end;
  if (nCode <> 0) and (sMsg <> '') then SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, sMsg);
end;

//淬炼原石

procedure TPlayObject.ClientOriginalStoneSmelt(nItemIdx, nType, nState: Integer; sData: string);
var
  buf                                   : array[0..6] of Integer;
  i, j, nLen                            : Integer;
  nCode                                 : Integer;
  ANpc                                  : TNormNpc;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  pUserItems                            : array[0..6] of pTUserItem;
  pStdItems                             : array[0..6] of pTStdItem;
  sMsg, sLable                          : string;
  sLableOK                              : string;
begin
  for i := 0 to 6 do begin
    m_sScriptParam[i] := '';
    pUserItems[i] := nil;
    pStdItems[i] := nil;
    buf[i] := 0;
  end;
  sLable := '';
  sLableOK := '';

  if m_ClickNPC = nil then Exit;
  ANpc := TNormNpc(m_ClickNPC);
  nLen := Length(sData);
  nLen := GetCodeMsgSize(nLen * 3 / 4);
  DeCodeBuffer(sData, @buf[1], nLen);
  buf[0] := nItemIdx;
  if m_btPermissionGM > 6 then begin
    SysMsg(Format('当前物品编号为:%d', [nItemIdx]), c_Red, t_Hint);
    SysMsg(Format('当前指令编号为:%d', [nType]), c_Red, t_Hint);
    SysMsg(Format('当前状态编号为:%d', [nState]), c_Red, t_Hint);
  end;
  nCode := 0;
  for i := 0 to 6 do begin
    for j := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[j];
      if UserItem.MakeIndex = buf[i] then begin
        pUserItems[i] := UserItem;
        pStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
        Break;
      end;
    end;
    if ((pUserItems[i] = nil) or (pStdItems[i] = nil)) and (buf[i] <> 0) then begin
      nCode := -1;
      sMsg := '你所要淬炼的宝石或者原石没有在你的包裹里发现';
      Break;
    end;
  end;
  {函数标签初始}
  sLable := '@@gemextract';
  if nState = 0 then sLable := sLable + 'OK';

  {函数触发开始}
  if (nCode = 0) then begin
    for i := 0 to 6 do begin
      if pUserItems[i] <> nil then begin
        m_sScriptParam[i] := IntToStr(pUserItems[i].MakeIndex);
{$IF USESDK = DEBUG}
        SysMsg(Format('物品%d:%d', [i, pUserItems[i].MakeIndex]), c_Pink, t_Hint);
{$IFEND}
      end;
    end;
    if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
      if (sLable <> '') then ANpc.GotoLable(Self, sLable, False);
    end;
  end;
  if (nCode <> 0) and (sMsg <> '') then SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, sMsg);
end;

//装备融合

procedure TPlayObject.ClientfuseequipItem(nState: Integer; nItemIdx, nItemIdx2: Integer; sData: string);
var
  buf                                   : array[0..3] of Integer;
  i, j, nLen                            : Integer;
  nCode                                 : Integer;
  ANpc                                  : TNormNpc;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  pUserItems                            : array[0..3] of pTUserItem;
  pStdItems                             : array[0..3] of pTStdItem;
  sMsg, sLable                          : string;
  sLableOK                              : string;
begin
  for i := 0 to 3 do begin
    m_sScriptParam[i] := '';
    pUserItems[i] := nil;
    pStdItems[i] := nil;
    buf[i] := 0;
  end;
  sLable := '';
  sLableOK := '';

  if m_ClickNPC = nil then Exit;
  ANpc := TNormNpc(m_ClickNPC);
  DeCodeBuffer(sData, @buf[2], SizeOf(Integer));
  buf[0] := nItemIdx;
  buf[1] := nItemIdx2;
  if m_btPermissionGM > 6 then begin
    SysMsg(Format('当前物品编号为:%d - %d - %d', [nItemIdx, nItemIdx2, buf[2]]), c_Red, t_Hint);
    SysMsg(Format('当前指令状态为:%d', [nState]), c_Red, t_Hint);
  end;

  nCode := 0;
  for i := 0 to 3 do begin
    for j := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[j];
      if UserItem.MakeIndex = buf[i] then begin
        pUserItems[i] := UserItem;
        pStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
        Break;
      end;
    end;
    if ((pUserItems[i] = nil) or (pStdItems[i] = nil)) and (buf[i] <> 0) then begin
      nCode := -1;
      sMsg := '你所要融合的装备没有在你的包裹里发现';
      Break;
    end;
  end;
  {函数标签初始}
  case nState of
    0: sLable := '@@fuseequip';
    1: sLable := '@@equipfuse';
    2: sLable := '@@xunzhangrh';
  end;

  {函数触发开始}
  if (nCode = 0) then begin
    for i := 0 to 3 do begin
      if pUserItems[i] <> nil then begin
        m_sScriptParam[i] := IntToStr(pUserItems[i].MakeIndex);
{$IF USESDK = DEBUG}
        SysMsg(Format('物品%d:%d', [i, pUserItems[i].MakeIndex]), c_Pink, t_Hint);
{$IFEND}
      end;
    end;
    if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
      if (sLable <> '') then ANpc.GotoLable(Self, sLable, False);
    end;
  end;
  if (nCode <> 0) and (sMsg <> '') then SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, sMsg);
end;

//装备精炼

procedure TPlayObject.ClientRefineItems(nType: Integer; nItemIdx, nItemIdx2: Integer; sData: string);
var
  buf                                   : array[0..6] of Integer;
  i, j, nLen                            : Integer;
  nCode                                 : Integer;
  ANpc                                  : TNormNpc;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  pUserItems                            : array[0..6] of pTUserItem;
  pStdItems                             : array[0..6] of pTStdItem;
  sMsg, sLable                          : string;
  sLableOK                              : string;
begin
  for i := 0 to 6 do begin
    m_sScriptParam[i] := '';
    pUserItems[i] := nil;
    pStdItems[i] := nil;
    buf[i] := 0;
  end;
  sLable := '';
  sLableOK := '';

  if m_ClickNPC = nil then Exit;
  ANpc := TNormNpc(m_ClickNPC);
  nLen := Length(sData);
  nLen := GetCodeMsgSize(nLen * 3 / 4);
  DeCodeBuffer(sData, @buf[1], nLen);
  buf[0] := nItemIdx;
  buf[6] := nItemIdx2;
  if m_btPermissionGM > 6 then begin
    SysMsg(Format('当前物品编号为:%d - %d', [nItemIdx, nItemIdx2]), c_Red, t_Hint);
    SysMsg(Format('当前指令编号为:%d', [nType]), c_Red, t_Hint);
  end;

  nCode := 0;
  for i := 0 to 6 do begin
    for j := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[j];
      if UserItem.MakeIndex = buf[i] then begin
        pUserItems[i] := UserItem;
        pStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
        Break;
      end;
    end;
    if ((pUserItems[i] = nil) or (pStdItems[i] = nil)) and (buf[i] <> 0) then begin
      nCode := -1;
      sMsg := '你所要精炼的装备或者原石没有在你的包裹里发现';
      Break;
    end;
  end;
  {函数标签初始}
  sLable := Format('@@NUhaiSuitUp%d', [nType]);
  {函数触发开始}
  if (nCode = 0) then begin
    for i := 0 to 6 do begin
      if pUserItems[i] <> nil then begin
        m_sScriptParam[i] := IntToStr(pUserItems[i].MakeIndex);
{$IF USESDK = DEBUG}
        SysMsg(Format('物品%d:%d', [i, pUserItems[i].MakeIndex]), c_Pink, t_Hint);
{$IFEND}
      end;
    end;
    if (IsEnvir(ANpc.m_PEnvir) and (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
      if (sLable <> '') then ANpc.GotoLable(Self, sLable, False);
    end;
  end;
  if (nCode <> 0) and (sMsg <> '') then SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, sMsg);
end;

procedure TPlayObject.ClientRepairItem(nParam1, nInt: Integer; nRepairType:
  Integer;
  sMsg: string);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  Merchant                              : TMerchant;
  sName                                 : string;
  boFind                                : Boolean;
begin
  UserItem := nil;
  boFind := False;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    //取自定义物品名称
    sName := '';
    ItemUnit.GetCustomItemName(UserItem, sName);

    if (UserItem.MakeIndex = nInt) and (CompareText(sMsg, sName) = 0) then begin
      boFind := True;
      Break;
    end;
  end;
  if not boFind or (UserItem = nil) then Exit;
  Merchant := UserEngine.FindMerchant(TObject(nParam1));
  if (Merchant <> nil) and
    (IsEnvir(Merchant.m_PEnvir) and
    (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
    (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) then
    Merchant.ClientRepairItem(Self, UserItem, nRepairType);
end;

procedure TPlayObject.ClientRequest(wIdent: word; nOp, nOpCode: Integer);
var
  Hum                                   : TPlayObject;
  i, nCount                             : Integer;
begin
  Hum := nil;
  nCount := 0;
{$IF USESDK = DEBUG}
  MainOutMessage(Format('请求消息:%d-%d-%d', [wIdent, nOp, nOpCode]));
{$IFEND}
  if nOp > 0 then Hum := TPlayObject(nOp);
  if (Hum <> nil) and (Hum is TPlayObject) then begin
    //检测是否是元神
    if (Hum <> nil) and (not Hum.m_boDeath) and (not Hum.m_boGhost) and
      (not Hum.m_boPneuma) and (not m_boDeath) and (not m_boGhost) and (not
      m_boPneuma) then begin
      case wIdent of
        CM_REQUESTMASTER: begin
            case nOpCode of
              1: begin                                                                              //招收徒弟
                  //Hum 徒弟 self 师傅
                  for i := 1 to 3 do if m_sMasterName[i] <> '' then Inc(nCount);
                  if nCount >= g_Config.nPrenticeMaxCount then begin
                    //徒弟太多
                    SysMsg('你已收满徒弟', c_Red, t_Hint);
                    Exit;
                  end;
                  if m_Abil.level < g_Config.nMasterLoLevel then begin
                    //自己等级不够
                    SysMsg('你的等级不够,不能收徒', c_Red, t_Hint);
                    Exit;
                  end;
                  if Hum.m_Abil.level >= g_Config.nPrenticeHiLevel then begin
                    //对方等级太高
                    SendDefMessage(CM_REQUESTMASTER, Integer(Self), 258, 12, 0, '对方等级太高');
                    Exit;
                  end;
                  if Hum.m_sMasterName[1] <> '' then begin
                    //对方有师傅
                    SysMsg('对方已经有师傅', c_Red, t_Hint);
                    Exit;
                  end;
                  Hum.SendDefMessage(CM_REQUESTMASTER, Integer(Self), 4, 0, 0, '');
                end;
              2: begin                                                                              //请求拜师
                  //Hum 师傅 self 徒弟
                  for i := 1 to 3 do if Hum.m_sMasterName[i] <> '' then
                      Inc(nCount);
                  if nCount >= g_Config.nPrenticeMaxCount then begin
                    SysMsg('对方已收满徒弟', c_Red, t_Hint);
                    Exit;
                  end;
                  if Hum.m_Abil.level < g_Config.nMasterLoLevel then begin
                    //对方等级不够
                    SysMsg('对方等级不够', c_Red, t_Hint);
                    Exit;
                  end;
                  if m_Abil.level >= g_Config.nPrenticeHiLevel then begin
                    //自己等级太高
                    SendDefMessage(CM_REQUESTMASTER, Integer(Self), 258, 12, 0, '你的等级太高');
                    Exit;
                  end;
                  if m_sMasterName[1] <> '' then begin
                    //自己已经有师傅
                    SysMsg('你已经有师傅', c_Red, t_Hint);
                    Exit;
                  end;
                  Hum.SendDefMessage(CM_REQUESTMASTER, Integer(Self), 3, 0, 0, '');
                end;
              3: begin                                                                              //同意拜师
                  //Hum 徒弟 Self 师傅
                  for i := 1 to 3 do if m_sMasterName[i] <> '' then Inc(nCount);
                  if (nCount < g_Config.nPrenticeMaxCount) and (m_Abil.level >=
                    g_Config.nMasterLoLevel) and
                    (Hum.m_Abil.level < g_Config.nPrenticeHiLevel) then begin
                    ChangeMasterName(m_sCharName, Hum.m_sCharName, True);
                    ChangeMasterName(Hum.m_sCharName, m_sCharName, False);
                    SendMeOnlineState(1);
                    CheckMaster();
                    Hum.CheckMaster();
                  end;
                end;
              4: begin                                                                              //同意收徒
                  //Hum 师傅  Self 徒弟
                  for i := 1 to 3 do if (Hum.m_sMasterName[i] <> '') then Inc(nCount);
                  if (nCount < g_Config.nPrenticeMaxCount) and (Hum.m_Abil.level >= g_Config.nMasterLoLevel) and
                    (m_Abil.level < g_Config.nPrenticeHiLevel) then begin
                    ChangeMasterName(m_sCharName, Hum.m_sCharName, False);
                    ChangeMasterName(Hum.m_sCharName, m_sCharName, True);
                    SendMeOnlineState(1);
                    CheckMaster();
                    Hum.CheckMaster();
                  end;
                end;
              259: Hum.SendDefMessage(CM_REQUESTMASTER, Integer(Self), 258, 16, 0, '对方拒绝收你为徒');
              260: Hum.SendDefMessage(CM_REQUESTMASTER, Integer(Self), 258, 18, 0, '对方拒绝拜你为师傅');
            end;
          end;
        CM_REQUESTDEAL: begin                                                                       //请求交易
            case nOpCode of
              0: begin
                  CmdChangeAttackMode(HAM_PEACE);
                  Hum.SendDefMessage(CM_REQUESTDEAL, Integer(Self), 1, 20, 0, m_sCharName + '申请和你交易');
                end;
              1: begin
                  CmdChangeAttackMode(HAM_PEACE);
                  Hum.ClientDealTry(m_sCharName);
                end;
            else
              Hum.SendDefMessage(CM_REQUESTDEAL, Integer(Self), 256, 16, 0, '对方拒绝与你交易');
            end;
          end;
      end;
    end;
  end;
end;

//同意或拒绝加为好友

procedure TPlayObject.ClientRespAddFriend(nRespCode: word; FriendName: string);
var
  human                                 : TPlayObject;
begin
  if nRespCode = 1 then begin                                                                       //同意
    human := UserEngine.GetPlayObject(FriendName);
    if (human <> nil) and (not human.m_boDeath) and (not human.m_boGhost) then begin
      {加到好有名单中}
      AddToFriendList(FriendName);
      {保存对方的好有名单}
      human.AddToFriendList(m_sCharName);
      SendMeOnlineState(1);
    end else begin                                                                                  //对方不在线
      SysMsg(FriendName + '当前不在线,请在他上线后再添加为好友.', c_Red, t_Hint);
    end;
  end else begin                                                                                    //拒绝
    human := UserEngine.GetPlayObject(FriendName);
    if (human <> nil) and (not human.m_boDeath) and (not human.m_boGhost) then begin
      human.SysMsg(m_sCharName + '拒绝了你的好友添加申请。', c_Red, t_Hint);
    end;
  end;
end;

function TPlayObject.ClientRide(): Boolean;
var
  i, nX, nY                             : Integer;
  nCheckCount                           : Integer;
  RidePet                               : TRidePet;
  btReLive, btType, btSoul              : byte;
  btRideFightSpeed                      : byte;
  boPetUnWater                          : Boolean;
  Hum                                   : TPlayObject;
begin
  Result := False;
  //判断是否使用了百变披风
  if (m_wBianshenImg <> 0) then begin
    if m_boRideOn then
      SendMsg(Self, RM_205, 0, 0, 0, 1, '')
    else
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    Exit;
  end;

  if m_boPneuma and (m_PneumaObject <> nil) then
    Hum := (m_PneumaObject as TPlayObject)
  else
    Hum := Self;

  if m_boRideOn then begin
    if m_boPneuma then begin
      btReLive := Hum.m_PetInfo[3].btReLive;                                                        //元神骑乘
      btType := Hum.m_PetInfo[3].btType;
      btRideFightSpeed := Hum.m_PetInfo[3].btRideFightSpeed;
      boPetUnWater := Hum.m_PetInfo[3].boUnWater;
      btSoul := Hum.m_PetInfo[3].btSoul;
      //化形骑战的灵兽  是否本体得下来?
      if (Hum.m_PetInfo[3].nMakeIndex = Hum.m_PetInfo[2].nMakeIndex) and (m_PneumaObject <> nil) then begin
        TPlayObject(m_PneumaObject).ClientRideOff();
      end;
    end else begin
      btReLive := Hum.m_PetInfo[2].btReLive;
      btType := Hum.m_PetInfo[2].btType;
      btRideFightSpeed := Hum.m_PetInfo[2].btRideFightSpeed;
      boPetUnWater := Hum.m_PetInfo[2].boUnWater;
      btSoul := Hum.m_PetInfo[2].btSoul;
    end;
  end else begin
    btReLive := Hum.m_PetInfo[0].btReLive;
    btType := Hum.m_PetInfo[0].btType;
    boPetUnWater := Hum.m_PetInfo[0].boUnWater;
    btSoul := Hum.m_PetInfo[0].btSoul;
  end;

  if btType < 11 then btType := m_btHorseType;

  if (btType in [11..PETMAXTYPE]) and (btReLive < 1) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('你可骑乘的灵兽(饱食状态)或马匹不在身边', c_Red, t_Hint);
    Exit;
  end;

  if (m_boPneuma and m_boInosculatePneuma) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('融合状态,无法骑乘灵兽。', c_Red, t_Hint);
    Exit;
  end;

  if m_boCatapultMode then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('投石车状态,禁止骑乘', c_Red, t_Hint);
    Exit;
  end;

  if m_wBianshenAppr <> 0 then begin
    if m_boRideOn then
      SendMsg(Self, RM_205, 0, 0, 0, 1, '')
    else
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('你已使用变身披风,禁止骑马', c_Red, t_Hint);
    Exit;
  end;

  //判断马、宠物的类型
  if (not (Hum.m_btHorseType in [1..10])) and (not (btType in [11..PETMAXTYPE])) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    m_boRideOn := False;
    m_boRideFightOn := False;
    m_Horse := nil;
    Exit;
  end;

  //判断是否行会老大
  if (m_btHorseType = 3) and (not IsGuildMaster) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('你不是行会长,不能骑黑马', c_Red, t_Hint);
    m_boRideOn := False;
    Exit;
  end;

  if (m_btHorseType = 2) and (not (IsGuildMaster and (g_CastleManager.IsCastleMember(Self) <> nil))) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('你不是沙城主,不能骑白马', c_Red, t_Hint);
    m_boRideOn := False;
    Exit;
  end;

  if (btType in [29..31, 35..37, 41]) and (m_btRulerLevel = 0) and (not g_Config.boUnRulerRidePet) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    if (btType in [27..29]) then
      SysMsg('你不是主宰者,不能骑帝王裂天犀', c_Red, t_Hint)
    else if btType in [35..37] then
      SysMsg('你不是主宰者,不能骑黄金战马', c_Red, t_Hint)
    else
      SysMsg('你不是主宰者,不能骑霜雪战熊', c_Red, t_Hint);
    m_boRideOn := False;
    Exit;
  end;

  if not m_boRideOn and (btType in [11..PETMAXTYPE]) and ((m_nDressShape and $000000C8) = 0) and (m_UseItems[U_RIDEDRESS].wIndex = 0) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    SysMsg('请先穿上骑宠专用服装才可以骑宠', c_Red, t_Hint);
    Exit;
  end;

  if not m_boRideOn and (btType in [26..28]) and (not m_PEnvir.m_MapFlag.boCanRideShark) then begin
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    Exit;
  end;

  //有宝盒也不让骑马
  if not m_boRideOn and m_boArrow then begin
    SysMsg('正在执行抢宝任务,不允许骑宠。', c_Red, t_Hint);
    if m_boRideOn then
      SendMsg(Self, RM_205, 0, 0, 0, 1, '')
    else
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    Exit;
  end;

  try
    nCheckCount := 0;
    //地图不允许骑马和骑宠
    if m_PEnvir.m_MapFlag.boNoRidePet and (not m_PEnvir.m_MapFlag.boRideOn) then begin
      nCheckCount := 1;
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
      m_boRideOn := False;
      m_boRideFightOn := False;                                                                     //下马状态
      HorseHide;
      SysMsg('本地图不允许骑宠。', c_Red, t_Hint);
      Exit;
    end;

    //判断地图是否允许骑马,宠物除外
    if not m_PEnvir.m_MapFlag.boRideOn and (m_btHorseType in [1..10]) and (btReLive < 1) then begin //不允许骑马
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
      m_boRideOn := False;                                                                          //下马状态
      nCheckCount := 1;
      HorseHide;
      Result := True;
      m_dwLastRide := GetTickCount;
      SysMsg('本地图不允许骑宠。', c_Red, t_Hint);
      Exit;
    end;
    //判断地图是否允许骑宠,马除外
    if m_PEnvir.m_MapFlag.boNoRidePet and (btType in [11..PETMAXTYPE]) and (not (m_btHorseType in [1..10])) then begin //本地图禁止骑豹子
      SendMsg(Self, RM_205, 0, 0, 0, 0, '');
      m_boRideOn := False;
      m_boRideFightOn := False;
      SysMsg('本地图不允许骑宠。', c_Red, t_Hint);
      Exit;
    end;

{$IF USESDK = DEBUG}
    SysMsg('骑宠类型:' + IntToStr(btType), c_Red, t_Hint);
{$IFEND}

    m_dwLastRide := GetTickCount;
    if m_boRideOn then begin                                                                        //骑乘中
      if btType in [11..PETMAXTYPE] then begin                                                      //灵兽
        nCheckCount := 4;
        if m_boRideFightOn or (btReLive < 2) then begin                                             //骑战中
          nCheckCount := 5;
          ClientRideOff();                                                                          //步行
          nCheckCount := 6;
        end else begin
          if m_PEnvir.m_MapFlag.boWaterNeed and (not (btType in [26..28])) and (not m_boUnWater) and (not boPetUnWater) then begin
            SendMsg(Self, RM_205, 0, 0, 0, 0, '');
            SysMsg('你没有开启避水护符(避水神符)或你的灵兽没有点化避水灵性,不能骑战', c_Red, t_Hint);
            ClientRideOff();
            Exit;
          end;
          nCheckCount := 7;
          m_boRideFightOn := True;
          RidePet.nFeature := GetFeatureToLong(Self);
          RidePet.btState := 1 + btRideFightSpeed;                                                  //1 骑战 2 骑战速度+1
          RidePet.btSoul := btSoul;                                                                 //魂佑灵兽
          SendRefMsg(RM_SITDOWN,
            m_btDirection,
            MakeLong(m_nCurrX, m_nCurrY),
            GetFeatureToLong(Self),
            1,
            EnCodeBuffer(@RidePet, SizeOf(TRidePet)));
          SendMsg(Self, RM_205, 0, 0, 0, 1, '');
          nCheckCount := 8;
          if m_boPneuma then Hum.SendPetInfo($08) else Hum.SendPetInfo($06);
          nCheckCount := 9;
        end;
      end else begin                                                                                //下马
        nCheckCount := 10;
        ClientRideOff();
        nCheckCount := 11;
      end;
      nCheckCount := 12;

      Result := True;
    end else begin
      nCheckCount := 13;
      if (Hum.m_Pet <> nil) and (btType in [11..PETMAXTYPE]) then begin                             //先骑宠物
        if (abs(m_nCurrX - Hum.m_Pet.m_nCurrX) > 2) or (abs(m_nCurrY - Hum.m_Pet.m_nCurrY) > 2) then begin
          SysMsg('你的坐骑不在身边。', c_Red, t_Hint);
          Exit;
        end;
        nCheckCount := 14;
        m_boRideOn := True;
        nCheckCount := 15;
        if m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, Hum.m_Pet.m_nCurrX, Hum.m_Pet.m_nCurrY, True) > 0 then begin
          m_nCurrX := Hum.m_Pet.m_nCurrX;
          m_nCurrY := Hum.m_Pet.m_nCurrY;
        end;
        nCheckCount := 16;
        if m_boPneuma then
          Hum.m_PetInfo[3] := Hum.m_PetInfo[0]
        else
          Hum.m_PetInfo[2] := Hum.m_PetInfo[0];

        m_btDirection := Hum.m_Pet.m_btDirection;
        nCheckCount := 19;

        RidePet.nFeature := GetFeatureToLong(Self);
        RidePet.btState := 0;
        RidePet.btSoul := btSoul;
        SendRefMsg(RM_SITDOWN,
          Hum.m_Pet.m_btDirection,
          MakeLong(Hum.m_Pet.m_nCurrX, Hum.m_Pet.m_nCurrY),
          GetFeatureToLong(Self),
          1,
          EnCodeBuffer(@RidePet, SizeOf(TRidePet)));

        SendMsg(Self, RM_205, 0, 0, 0, 1, '');
        nCheckCount := 20;
        if m_boPneuma then Hum.SendPetInfo($07) else Hum.SendPetInfo($02);

        //化形骑战, 元神直接骑战状态
        if (not m_boPneuma) and (m_PneumaObject <> nil) and (btReLive > 2) {and (m_MagicSkills[SKILL_CLONEPET] <> nil)} then begin
          Hum.m_PetInfo[3] := Hum.m_PetInfo[0];
          btRideFightSpeed := Hum.m_PetInfo[3].btRideFightSpeed;
          TPlayObject(m_PneumaObject).m_boRideOn := True;
          TPlayObject(m_PneumaObject).m_boRideFightOn := True;
          //化形骑战的元神有御兽天衣的外观
          m_PneumaObject.m_nDressShape := MakeLong($00C8, HiWord(m_PneumaObject.m_nDressShape));

          RidePet.nFeature := m_PneumaObject.GetFeatureToLong(Self);
          RidePet.btState := 1 + btRideFightSpeed;                                                  //1 骑战 2 骑战速度+1
          RidePet.btSoul := btSoul;
          m_PneumaObject.SendRefMsg(RM_SITDOWN,
            m_PneumaObject.m_btDirection,
            MakeLong(m_PneumaObject.m_nCurrX, m_PneumaObject.m_nCurrY),
            m_PneumaObject.GetFeatureToLong(Self),
            1,
            EnCodeBuffer(@RidePet, SizeOf(TRidePet)));
          m_PneumaObject.SendMsg(m_PneumaObject, RM_205, 0, 0, 0, 1, '');
          m_PneumaObject.SendRefMsg(RM_510, 1, 0, 180, 0, '');

          m_PneumaObject.FeatureChanged;
          m_PneumaObject.RecalcAbilitys();
        end;
        //删除灵兽
        Hum.PetHide(Hum.m_PetInfo[0].nMakeIndex);
        Result := True;
        nCheckCount := 22;
      end else if (m_Horse <> nil) and (m_btHorseType in [1..10]) then begin                        //上马
        nCheckCount := 23;
        //判断马和人的距离
        if (abs(m_nCurrX - m_Horse.m_nCurrX) > 2) or (abs(m_nCurrY - m_Horse.m_nCurrY) > 2) then begin
          SysMsg('你的马不在身边。', c_Red, t_Hint);
          Exit;
        end;
        nCheckCount := 24;
        m_boRideOn := True;
        if m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_Horse.m_nCurrX, m_Horse.m_nCurrY, True) > 0 then begin
          m_nCurrX := m_Horse.m_nCurrX;
          m_nCurrY := m_Horse.m_nCurrY;
        end;
        nCheckCount := 25;
        m_btDirection := m_Horse.m_btDirection;
        nCheckCount := 26;
        RidePet.nFeature := GetFeatureToLong(Self);
        RidePet.btState := 0;
        SendRefMsg(RM_SITDOWN,
          m_Horse.m_btDirection,
          MakeLong(m_Horse.m_nCurrX, m_Horse.m_nCurrY),
          GetFeatureToLong(Self),
          1,
          EnCodeBuffer(@RidePet, SizeOf(RidePet)));
        SendMsg(Self, RM_205, 0, 0, 0, 1, '');
        nCheckCount := 27;
        SendDefMessage(34977, m_Horse.m_wAppr, 612, 2, 0, '');
        //删除马宝宝
        nCheckCount := 28;
        HorseHide;
        Result := True;
      end;
    end;
    FeatureChanged;
    RecalcAbilitys();                                                                               //计算骑战属性
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  except
    on E: Exception do
      MainOutMessage(m_sCharName + '骑马下马出错:#' + IntToStr(nCheckCount) + ' ' + E.Message);
  end;

end;

procedure TPlayObject.ClientRideOff;
var
  i, nX, nY, nMakeIndex                 : Integer;
  Hum                                   : TPlayObject;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  btPet                                 : byte;
begin
  if m_boRideOn then begin
    if m_boPneuma and (m_PneumaObject <> nil) then begin
      Hum := TPlayObject(m_PneumaObject);
      Hum.GetUserItemByMakeIndex(Hum.m_PetInfo[3].nMakeIndex, UserItem);                            //元神骑乘
      btPet := Hum.m_PetInfo[3].btType;
    end else begin
      Hum := Self;
      Hum.GetUserItemByMakeIndex(Hum.m_PetInfo[2].nMakeIndex, UserItem);
      btPet := Hum.m_PetInfo[2].btType;
    end;

    if (btPet in [11..PETMAXTYPE]) and (UserItem = nil) then Exit;

    if (not (Hum.m_btHorseType in [1..10])) and (not (btPet in [11..PETMAXTYPE])) then begin
      m_boRideOn := False;
      m_boRideFightOn := False;
      HorseName := '';
      Exit;
    end;

    if m_boPneuma then begin
      nMakeIndex := Hum.m_PetInfo[3].nMakeIndex;
      Hum.m_PetInfo[3].nMakeIndex := 0;
      Hum.m_PetInfo[3].wLevel := 0;
      Hum.m_PetInfo[3].btType := 0;
      Hum.m_PetInfo[3].btReLive := 0;
      Hum.m_PetInfo[3].btRideFightSpeed := 0;
    end else begin
      nMakeIndex := Hum.m_PetInfo[2].nMakeIndex;
      Hum.m_PetInfo[2].nMakeIndex := 0;
      Hum.m_PetInfo[2].wLevel := 0;
      Hum.m_PetInfo[2].btType := 0;
      Hum.m_PetInfo[2].btReLive := 0;
      Hum.m_PetInfo[2].btRideFightSpeed := 0;

      //化形骑战的灵兽
      if (Hum.m_PetInfo[3].nMakeIndex = nMakeIndex) and (m_PneumaObject <> nil) then begin
        Hum.m_PetInfo[3].nMakeIndex := 0;
        Hum.m_PetInfo[3].wLevel := 0;
        Hum.m_PetInfo[3].btType := 0;
        Hum.m_PetInfo[3].btReLive := 0;
        Hum.m_PetInfo[3].btRideFightSpeed := 0;

        TPlayObject(m_PneumaObject).m_boRideOn := False;
        TPlayObject(m_PneumaObject).m_boRideFightOn := False;

        //取消御兽天衣的外观
        if m_PneumaObject.m_UseItems[0].wIndex = 0 then
          m_PneumaObject.m_nDressShape := 0
        else begin
          StdItem := UserEngine.GetStdItem(m_PneumaObject.m_UseItems[0].wIndex);
          if StdItem = nil then
            m_PneumaObject.m_nDressShape := 0
          else
            m_PneumaObject.m_nDressShape := MakeLong(MakeWord(StdItem.Shape, $00), HiWord(m_PneumaObject.m_nDressShape));
        end;

        m_PneumaObject.SendRefMsg(RM_SITDOWN,
          m_PneumaObject.m_btDirection,
          MakeLong(m_PneumaObject.m_nCurrX, m_PneumaObject.m_nCurrY),
          m_PneumaObject.GetFeature(Self),
          0,
          '');
        m_PneumaObject.SendMsg(m_PneumaObject, RM_205, 0, 0, 0, 0, '');
        m_PneumaObject.FeatureChanged;
        m_PneumaObject.RecalcAbilitys();                                                            //计算骑战属性
        m_PneumaObject.SendMsg(m_PneumaObject, RM_ABILITY, 0, 0, 0, 0, '');
        m_PneumaObject.SendMsg(m_PneumaObject, RM_SUBABILITY, 0, 0, 0, 0, '');

        //融合元神需要强制刷新外观
        if TPlayObject(m_PneumaObject).m_boInosculatePneuma then
          m_PneumaObject.SendRefMsg(RM_TURN,
            m_PneumaObject.m_btDirection,
            m_PneumaObject.m_nCurrX,
            m_PneumaObject.m_nCurrY,
            CalcCent(m_PneumaObject.m_WAbil.dwHP, m_PneumaObject.m_WAbil.dwMaxHP),
            m_PneumaObject.GetShowName);
      end;
    end;
  end else begin
    nMakeIndex := m_PetInfo[0].nMakeIndex;
    btPet := m_PetInfo[0].btType;
  end;

  if (btPet in [26..28]) and (not m_PEnvir.m_MapFlag.boCanRideShark) then begin                     //鲨鱼在普通地图不能出现
    PetHide(nMakeIndex);
  end;

  if m_boRideOn and (btPet in [11..PETMAXTYPE]) then begin                                          //踏云豹在任何地图都可以去
    if (Hum.m_Pet = nil) and (Hum.m_PetInfo[0].nMakeIndex = 0) then begin
      Hum.PetShow(UserItem.MakeIndex);

      if Hum.m_Pet <> nil then begin
        if m_PEnvir.MoveToMovingObject(Hum.m_Pet.m_nCurrX, Hum.m_Pet.m_nCurrY, Hum.m_Pet, m_nCurrX, m_nCurrY, True) > 0 then begin
          Hum.m_Pet.m_nCurrX := m_nCurrX;
          Hum.m_Pet.m_nCurrY := m_nCurrY;
        end;
        Hum.m_Pet.TurnTo(m_btDirection);
        Hum.m_Pet.GetLeftPosition(nX, nY);
        if m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, nX, nY, True) > 0 then begin
          m_nCurrX := nX;
          m_nCurrY := nY;
        end;
      end;
    end else begin
      m_defMsg := MakeDefaultMsg(34977, 0, 100, 0, 0);
      Hum.SendSocket(@m_defMsg, EnCodeBuffer(@nMakeIndex, 4));
    end;
  end else if m_PEnvir.m_MapFlag.boRideOn and (m_btHorseType in [1..10]) then begin                 //允许骑马地图,则出现马
    if (m_Horse = nil) then begin
      m_Horse := MakeSlave(HorseName, 7, 7, 100, 24 * 60 * 60, -1);
      if m_Horse <> nil then begin
        if not GetRightPosition(nX, nY) then begin
          nX := m_nCurrX;
          nY := m_nCurrY;
        end;
        if m_PEnvir.MoveToMovingObject(m_Horse.m_nCurrX, m_Horse.m_nCurrY, m_Horse, nX, nY, True) > 0 then begin
          m_Horse.m_nCurrX := nX;
          m_Horse.m_nCurrY := nY;
        end;
        m_Horse.TurnTo(m_btDirection);
        SendDefMessage(34977, m_Horse.m_wAppr, 612, 1, 0, '');
      end;
    end;
  end else begin                                                                                    //不允许骑马
    //不允许骑马的地图
    if m_Horse <> nil then begin                                                                    //删除马宝宝
      HorseHide;
      SysMsg('您的' + HorseName + '无法进入此地,暂时在外面等候', c_Red, t_Hint);
    end;
  end;

  if m_boRideOn then begin                                                                          //在骑马,则下马
    m_boRideOn := False;
    m_boRideFightOn := False;
    SendRefMsg(RM_SITDOWN, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), GetFeatureToLong(Self), 0, '');
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
  end;
end;

//CM_RUN命令的处理

function TPlayObject.ClientRunXY(wIdent: word; nX, nY: Integer; nFlag: Integer;
  var dwDelayTime: LongWord): Boolean;                                                              //004CB11C
var
  nDir                                  : Integer;
  dwCheckTime                           : LongWord;
  runOK                                 : Boolean;
  nPinjunTime                           : Integer;
  nCheckTime                            : Integer;
  btRideFightSpeed                      : byte;
  nStep                                 : byte;
begin
  Result := False;
  dwDelayTime := 0;
  if (not m_boCanRun) or (m_wShopItemCount > 0) or (m_boCatapultAttackMode) then Exit;

  if not CheckCanOperate(cRun) then Exit;

  if (not g_Config.boDisableM2SpeedCtrl) then begin
    //10指令时间控制
    if m_nRunCount = 0 then m_FirstRunTick := GetTickCount;
    m_nWalkCount := 0;
    Inc(m_nRunCount);
    if m_nRunCount >= 11 then begin
      nPinjunTime := (GetTickCount - m_FirstRunTick) div 10;
{$IF USESDK = DEBUG}
      //SysMsg('跑10次平均时间:'+inttostr(nPinjunTime),c_blue,t_hint);
{$IFEND}
      m_FirstRunTick := GetTickCount;
      m_nRunCount := 0;
      if nPinjunTime < g_Config.n10RunTIme then begin
        if m_boTestSpeedMode then
          SysMsg(Format('10次跑超速!限制:%d,当前:%d', [g_Config.n10RunTIme, nPinjunTime]), c_Red, t_Hint);
        Exit;
      end;
    end;

    if nFlag <> wIdent then begin
      if not CheckActionStatus(wIdent, dwDelayTime) then begin
        m_boFilterAction := False;
        Exit;
      end;
      m_boFilterAction := True;
      dwCheckTime := GetTickCount - m_dwMoveTick;
      //上次移动时间和本次移动时间间隔
      if (dwCheckTime < g_Config.dwRunIntervalTime + m_dwWalkTick) then begin                       //两次行动间隔比要求的小,则可能加速
        if m_dwWalkTick = 0 then
          Inc(m_dwMoveCount);                                                                       //增加移动次数
        dwDelayTime := _Max(0, Integer(g_Config.dwRunIntervalTime) -
          Integer(dwCheckTime));                                                                    //计算超过的时间
        if dwDelayTime > g_Config.dwRunIntervalTime div 3 then begin                                //在默认的67%-100%之间的,允许4次
          if m_dwMoveCount >= 4 then begin
            m_dwMoveTick := GetTickCount();
            m_dwMoveCount := 0;
            dwDelayTime := g_Config.dwRunIntervalTime div 3;
            if m_boTestSpeedMode then
              SysMsg('跑步忙复位!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
          end else m_dwMoveCount := 0;
          Exit;
        end else begin                                                                              //超速达到33%以上的,直接认为超速
          if m_boTestSpeedMode then
            SysMsg('跑步忙!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
          Exit;
        end;
      end;
    end;
  end;

  m_dwMoveTick := GetTickCount();
  nCheckTime := GetTickCount - m_dwDoMotaeboMoveTick;
  if nCheckTime < g_Config.dwRunIntervalTime div 4 then Exit;
  m_dwDoMotaeboMoveTick := GetTickCount();

  m_boMoveSuccess := False;
  nDir := GetNextDirection(m_nCurrX, m_nCurrY, nX, nY);

  if m_boPneuma and (m_PneumaObject <> nil) then begin
    btRideFightSpeed := TPlayObject(m_PneumaObject).m_PetInfo[3].btRideFightSpeed;
  end else begin
    btRideFightSpeed := m_PetInfo[2].btRideFightSpeed;
  end;

  nStep := _Max(abs(m_nCurrX - nX), abs(m_nCurrY - nY));

  if ((m_boRideOn and not m_boRideFightOn)) or m_boFlyer or
    (m_boRideOn and (btRideFightSpeed = 1) and (m_boRideFightOn)) or
    (m_btGodRunTime > 0) then begin
    if nStep > 2 then begin
      runOK := HorseRunTo(nDir, False);
    end else if nStep > 1 then begin
      runOK := Runto(nDir, False)
    end else
      runOK := WalkTo(nDir, False);
  end else if (m_dwTotemStatusTimeOutTick[3] > 0) or (m_wStatusTimeArr[STATE_GRAVITY] <> 0) then begin //重力图腾
    runOK := WalkTo(nDir, False)
  end else
    runOK := Runto(nDir, False);

  if runOK then begin
    if m_boTransparent and (m_boHideMode) then                                                      //隐身模式跑动效果消失
      m_wStatusTimeArr[STATE_TRANSPARENT] := 1;                                                     //004CB212

    if m_boMoveSuccess or ((m_nCurrX = nX) and (m_nCurrY = nY)) then Result := True;

    if Result then                                                                                  //行走有伤害
      RunStepToDamage(nStep);

{$IF USESDK = DEBUG}
    if not Result then
      SysMsg(Format('移动失败:目标坐标:(%d,%d),新坐标:(%d,%d)', [m_nCurrX, m_nCurrY, nX, nY]), c_Pink, t_Hint);
{$IFEND}
    Dec(m_nHealthTick, 60);
    Dec(m_nSpellTick, 10);
    m_nSpellTick := _Max(0, m_nSpellTick);
    Dec(m_nPerHealth);
    Dec(m_nPerSpell);
  end else begin
    m_dwMoveCount := 0;
    m_dwMoveCountA := 0;
  end;
  m_dwWalkTick := 0;
end;

procedure TPlayObject.ClientSendBlessMsg(NPC: Integer; MsgFlag: Integer; sMsg:
  string);
var
  ANpc                                  : TNormNpc;
  sLabel                                : string;
begin
  if not g_Config.boSendCustemMsg then begin
    SysMsg(g_sSendCustMsgCanNotUseNowMsg, c_Red, t_Hint);
    Exit;
  end;

  ANpc := UserEngine.FindMerchant(TObject(NPC));

  if ANpc = nil then ANpc := UserEngine.FindNPC(TObject(NPC));
  if ANpc = nil then begin
    UserEngine.SendBroadCastMsgExt(m_sCharName + '祝福:' + sMsg, t_Flymsg);
    Exit;
  end;

  if (IsEnvir(ANpc.m_PEnvir) and
    (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and
    (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
    m_sScriptParam[0] := sMsg;
    if MsgFlag = 2 then
      sLabel := '@@blessname'
    else
      sLabel := '@@sendbless';
    if not ANpc.GotoLable(Self, sLabel, False) then
      UserEngine.SendBroadCastMsgExt(m_sCharName + '祝福:' + sMsg, t_Flymsg);
    Exit;
  end;
end;

{客户端发送的包裹顺序}

procedure TPlayObject.ClientSetBagOrder(nItemCount: Integer; sData: string);
var
  BagItemOrder                          : array[0..125] of TClientItemOrder;
  i, ii                                 : Integer;
begin
  if m_boPneuma then Exit;                                                                          //元神不发送
  if nItemCount > 125 then
    nItemCount := 125;
  DeCodeBuffer(sData, @BagItemOrder[0], nItemCount * SizeOf(TClientItemOrder));
  for i := 0 to nItemCount - 1 do begin
    ii := m_ItemList.IndexOf(BagItemOrder[i].MakeIndex);
    if ii >= 0 then
      m_ItemList.Pos[ii] := BagItemOrder[i].Order;
  end;
end;

//把包裹顺序发送到客户端

procedure TPlayObject.ClientSendBagOrder();
var
  BagOrder                              : array[0..125] of TClientItemOrder;
  i                                     : Integer;
  sData                                 : string;
  UserItem                              : pTUserItem;
  bo                                    : Boolean;
begin
  if m_boPneuma then Exit;                                                                          //元神不发送

  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    BagOrder[i].MakeIndex := UserItem.MakeIndex;
    BagOrder[i].Order := m_ItemList.Pos[i];
    if i >= 125 then
      Break;
  end;
  m_defMsg := MakeDefaultMsg($46, 0, 0, 0, m_ItemList.Count);
  if m_ItemList.Count <> 0 then
    SendSocket(@m_defMsg, EnCodeBuffer(@BagOrder[0], m_ItemList.Count * SizeOf(TClientItemOrder)));
end;

procedure TPlayObject.ClientSetTigerTarget(nMonID, nOp, nX, nY: Integer);
var
  Monster                               : TBaseObject;
begin
  if (m_Tiger <> nil) and (not m_Tiger.m_boDeath) and (not m_Tiger.m_boGhost) then begin

    if (nOp = 0) or (nOp = 257) then begin
      if (nMonID > 0) and (CretInNear10XY(TBaseObject(nMonID), m_nCurrX, m_nCurrY)) then begin
        Monster := TBaseObject(nMonID);
        if (Monster <> nil) and (Monster <> m_Tiger) and (not Monster.m_boDeath) and (not Monster.m_boGhost) then begin
          if IsProperTarget(Monster) then begin
            m_Tiger.m_FirstTargetCret := Monster;
            m_Tiger.SetTargetCreat(Monster);
            SetTargetCreat(Monster);
            if m_TorDDM.Tiger.DB.Dragon > 0 then
              SendDefMessage(CM_TIGERATTACK, nMonID, 2, 0, 0, '')
            else
              SendDefMessage(CM_TIGERATTACK, nMonID, 1, 0, 0, '');
          end;
        end;
      end else
        m_Tiger.DelTargetCreat;
      Exit;
    end;

    case HiByte(nOp) of
      0: begin
          m_Tiger.m_nMissionX := -1;
          m_Tiger.m_nMissionY := -1;
          m_Tiger.m_boMission := False;
          m_Tiger.DelTargetCreat;
          SendDefMessage(CM_TIGERATTACK, 0, 3, 0, 0, '');
        end;
      2: begin
          if m_TorDDM.Tiger.DB.Dragon > 0 then begin
            if (m_nCurrX - nX <= 10) and (m_nCurrY - nY <= 10) then begin
              m_Tiger.m_nMissionX := nX;
              m_Tiger.m_nMissionY := nY;
              m_Tiger.m_boMission := True;
              SendDefMessage(CM_TIGERATTACK, 0, 4, 0, 0, '');
            end;
          end;
        end;
    end;
  end;
end;

//CM_SITDOWN

function TPlayObject.ClientSitDownHit(nX, nY, nDir: Integer; var dwDelayTime:
  LongWord): Boolean;                                                                               //004CC248
var
  dwCheckTime                           : LongWord;
begin
  Result := False;
  if not CheckCanOperate(cDigUp) then Exit;
  if not g_Config.boDisableM2SpeedCtrl then begin
    dwCheckTime := GetTickCount - m_dwTurnTick;

    if dwCheckTime < g_Config.dwTurnIntervalTime then begin
      dwDelayTime := g_Config.dwTurnIntervalTime - dwCheckTime;
      Exit;
    end;
    m_dwTurnTick := GetTickCount;
  end;
  SendRefMsg(RM_BUTCH, m_btDirection, m_nCurrX, m_nCurrY, 0, '');
  //执行脚本:挖宝
  if g_Config.boStartMapEvent then begin
    StartMapEventOfButch();
  end;
  Result := True;
end;

//魔法(CM_SPELL命令的处理)

function TPlayObject.ClientSpellXY(wIdent: word; nKey: Integer; nTargetX,
  nTargetY: Integer; TargeTBaseObject: TBaseObject; boLateDelivery: Boolean; var
  dwDelayTime: LongWord): Boolean;                                                                  //004CBCEC
var
  UserMagic                             : pTUserMagic;
  nSpellPoint                           : Integer;
  n14                                   : Integer;
  BaseObject                            : TBaseObject;
  dwCheckTime                           : LongWord;
  boIsWarrSkill                         : Boolean;
  NextMagic                             : pTUserMagic;
  wPercen                               : Word;
  function isNoCheckTimeSkill(wMagIdx: Integer): Boolean;
  begin
    Result := wMagIdx in [SKILL_SHIELD, SKILL_MOOTEBO, SKILL_42, SKILL_59, SKILL_60, SKILL_61, SKILL_62, SKILL_70];
  end;
begin
  Result := False;
  dwDelayTime := 0;
  if m_boPneuma and m_PEnvir.m_MapFlag.boNoPneuma then Exit;                                        //元神在不允许释放的地图,禁止攻击

  if (not m_boCanSpell) or (m_wShopItemCount > 0) or (m_boCatapultAttackMode) then Exit;

  if (m_wBianshenAppr > 0) and (m_boAttackMode = False) then Exit;                                  //2016.06.22 支持ChangeAppr变身支持攻击

  if (m_boRideOn and not m_boRideFightOn) then Exit;                                                //骑马不允许使用魔法

  if not CheckCanOperate(cMagHit, nKey) then Exit;

  UserMagic := GetMagicInfo(nKey);                                                                  //根据MagicID获取魔法

  if (nKey in [78..81, 83, 85]) then begin
    if (not m_boPneuma) and (m_PneumaObject <> nil) then begin
      if m_PneumaObject.m_boPneumaEffMode then begin
        SysMsg('元神灵珠状态不允许使用组合技能。', c_Red, t_Notice);
        Exit;
      end;
      UserMagic := m_PneumaObject.GetMagicInfo(nKey);
    end;
  end;

  if (nKey in [100..105]) and (not m_boPneuma) and (m_PneumaObject <> nil) and (not g_Config.boMergeSkillByOneself) then begin
    if m_PneumaObject.m_boPneumaEffMode then begin
      SysMsg('元神灵珠状态不允许使用组合技能。', c_Red, t_Notice);
      Exit;
    end;
  end;

  if UserMagic = nil then Exit;

  //检查是否为本地图禁止使用的技能
  if m_PEnvir.ForbidMagic(UserMagic.MagicInfo.sMagicName) then begin
    SysMsg('本地图禁止使用' + UserMagic.MagicInfo.sMagicName, c_Red, t_Hint);
    Exit;
  end;

  //检查是否为禁止使用该技能状态
  if m_dwStopMagic[UserMagic.GetMagIdx] > GetTickCount() then begin
    SysMsg('当前' + UserMagic.MagicInfo.sMagicName + '被禁止使用状态', c_Red, t_Hint);
    Exit;
  end;

  boIsWarrSkill := MagicManager.IsWarrSkill(UserMagic.GetMagIdx);
  if (not g_Config.boDisableM2SpeedCtrl) then begin
    if (not boLateDelivery) and not boIsWarrSkill and not isNoCheckTimeSkill(UserMagic.GetMagIdx) then begin //战士技能不做处理
//      if not CheckActionStatus(wIdent, dwDelayTime) then begin
//        m_boFilterAction := False;
//        Exit;
//      end;
      m_boFilterAction := True;
      dwCheckTime := GetTickCount - m_dwMagicAttackTick;
      if dwCheckTime < m_dwMagicAttackInterval then begin
        Inc(m_dwMagicAttackCount);
        dwDelayTime := m_dwMagicAttackInterval - dwCheckTime;
        if dwDelayTime > g_Config.dwMagicHitIntervalTime div 3 then begin
          if m_dwMagicAttackCount >= 4 then begin
            m_dwMagicAttackTick := GetTickCount();
            m_dwMagicAttackCount := 0;
            dwDelayTime := g_Config.dwMagicHitIntervalTime div 3;
            if m_boTestSpeedMode then
              SysMsg('魔法忙复位!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
          end else
            m_dwMagicAttackCount := 0;
          Exit;
        end else begin
          if m_boTestSpeedMode then
            SysMsg('魔法忙!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
          Exit;
        end;
      end;
    end;
    Dec(m_nSpellTick, 450);
    m_nSpellTick := _Max(0, m_nSpellTick);

    if boIsWarrSkill then begin                                                                     //战士的技能不做处理
      //m_dwMagicAttackInterval:=0;
      //m_dwMagicAttackInterval:=g_Config.dwMagicHitIntervalTime; //01/21 改成此行
    end else begin
      m_dwMagicAttackInterval := UserMagic.MagicInfo.dwDelayTime + g_Config.dwMagicHitIntervalTime;
    end;
    m_dwMagicAttackTick := GetTickCount();
  end;

  CheckProwlMagic;                                                                                  //检查是否有潜行

  case UserMagic.GetMagIdx of                                                                       //
    SKILL_ERGUM {12}: begin                                                                         //刺杀剑法
        if m_MagicSkills[12] <> nil then begin
          if not m_boUseThrusting then begin
            ThrustingOnOff(True);
            SendSocket(nil, '+LNG');
          end else begin
            ThrustingOnOff(False);
            SendSocket(nil, '+ULNG');
          end;
        end;
        Result := True;
      end;
    SKILL_BANWOL {25}: begin                                                                        //半月弯刀
        if m_MagicSkills[25] <> nil then begin
          if not m_boUseHalfMoon then begin
            HalfMoonOnOff(True);
            SendSocket(nil, '+WID');
          end else begin
            HalfMoonOnOff(False);
            SendSocket(nil, '+UWID');
          end;
        end;
        Result := True;
      end;
    SKILL_FIRESWORD {26}: begin                                                                     //烈火剑法
        if m_MagicSkills[26] <> nil then begin
          if AllowFireHitSkill then begin
            nSpellPoint := GetSpellPoint(UserMagic);
            if m_WAbil.dwMP >= nSpellPoint then begin
              if nSpellPoint > 0 then begin
                DamageSpell(nSpellPoint);
                //HealthSpellChanged();
              end;
              SendSocket(nil, '+FIR');
            end;
          end;
        end;
        Result := True;
      end;
    SKILL_MOOTEBO {27}, SKILL_62: begin                                                             //野蛮冲撞 ,突斩
        Result := True;
        if (GetTickCount - m_dwDoMotaeboTick) > 3 * 1000 then begin
          m_dwDoMotaeboTick := GetTickCount();
          m_btDirection := nTargetX;
          nSpellPoint := GetSpellPoint(UserMagic);
          if m_WAbil.dwMP >= nSpellPoint then begin
            if nSpellPoint > 0 then begin
              DamageSpell(nSpellPoint);
              //HealthSpellChanged();
            end;
            if DoMotaebo(m_btDirection, UserMagic.btLevel, UserMagic.GetMagIdx) then
              TrainSkill(UserMagic, Random(3) + 1, 1000);
          end;
        end;
      end;
    SKILL_WINDTEBO, SKILL_75, SKILL_77{, SKILL_176}: begin
        m_btDirection := nTargetX;
        nSpellPoint := GetSpellPoint(UserMagic);
        if m_WAbil.dwMP >= nSpellPoint then begin
          if nSpellPoint > 0 then begin
            DamageSpell(nSpellPoint);
          end;
          if MagDoBatfly(UserMagic, nTargetX, nTargetY) then begin
            Result := True;
            TrainSkill(UserMagic, Random(3) + 1, 1000);
          end;
        end;
      end;
    SKILL_40: begin                                                                                 //双龙斩
        if m_MagicSkills[40] <> nil then begin
          if not m_boCrsHitkill then begin
            SkillCrsOnOff(True);
            SendSocket(nil, '+CRS');
          end else begin
            SkillCrsOnOff(False);
            SendSocket(nil, '+UCRS');
          end;
        end;
        Result := True;
      end;
    SKILL_43: begin                                                                                 //抱月刀
        if m_MagicSkills[43] <> nil then begin
          if not m_bo43Skill then begin
            Skill43OnOff(True);
            SendSocket(nil, '+CIR');
          end else begin
            Skill43OnOff(False);
            SendSocket(nil, '+UCIR');
          end;
        end;
        Result := True;
      end;
    SKILL_44: begin                                                                                 //雷霆剑
        if m_MagicSkills[44] <> nil then begin
          if AllowThunderHitSkill then begin
            nSpellPoint := GetSpellPoint(UserMagic);
            if m_WAbil.dwMP >= nSpellPoint then begin
              if nSpellPoint > 0 then begin
                DamageSpell(nSpellPoint);
                //HealthSpellChanged();
              end;
              SendSocket(nil, '+THU');                                                              //'+FIR');
            end;
          end;
        end;
        Result := True;
      end;
    SKILL_59: begin                                                                                 //破击剑法
        if m_MagicSkills[59] <> nil then begin
          if not m_bo59Skill then begin
            Skill59OnOff(True);
            SendSocket(nil, '+PJ');
          end else begin
            Skill59OnOff(False);
            SendSocket(nil, '+UPJ');
          end;
        end;
        Result := True;
      end;
    SKILL_60: begin                                                                                 //破盾斩
        if m_MagicSkills[60] <> nil then begin
          if not m_bo60Skill then begin
            Skill60OnOff(True);
            SendSocket(nil, '+PD');
          end else begin
            Skill60OnOff(False);
            SendSocket(nil, '+UPD');
          end;
        end;
        Result := True;
      end;
  else begin
      BaseObject := nil;
      //检查目标角色,与目标座标误差范围,如果在误差范围内则修正目标座标
      if CretInNearXY(TargeTBaseObject, nTargetX, nTargetY) then begin
        BaseObject := TargeTBaseObject;
        nTargetX := BaseObject.m_nCurrX;
        nTargetY := BaseObject.m_nCurrY;
      end;
      //元神目标修正
      if ((nTargetX = 0) or (nTargetY = 0)) and m_boPneuma then begin
        nTargetX := m_nCurrX;
        nTargetY := m_nCurrY;
      end;
      //铁血神技处理
      {if (UserMagic.GetMagIdx in [SKILL_220..SKILL_235]) then begin
        NextMagic := nil;
        NextMagic := MagicManager.GetMagicOrder(Self, m_btMagicOrder);
        Inc(m_btMagicOrder);
        if NextMagic <> nil then begin
          UserMagic := NextMagic;
          if m_btMagicOrder = $01 then begin
            wPercen := Round((m_WAbil.wMaxVitaLity * 5) / 10);
            if m_wVitaLity < wPercen then begin
              SysMsg('元气值不足', c_Red, t_Hint);
              Exit;
            end;
            //减少元气
            DamageVitaLity(wPercen);
            SendRefMsg(RM_510, m_nCurrX, m_nCurrY, 321, 0, '');
          end;
        end;
      end;   }

      //魔法攻击(法师、道士的技能)
      Result := DoSpell(UserMagic, nTargetX, nTargetY, BaseObject);
      if not Result then begin
        SendMsg(Self, RM_MAGICFIREFAIL, 0, 0, 0, 0, '');
      end ;{else if (UserMagic.GetMagIdx in [SKILL_220..SKILL_235]) then begin                        //铁血技能处理
        NextMagic := nil;
        NextMagic := MagicManager.GetMagicOrder(Self, m_btMagicOrder);
        if (NextMagic <> nil) and (m_boComboMagic) then begin
          case m_btJob of
            0: SendDelayMsg(Self, 3017, NextMagic.GetMagIdx, nTargetX, nTargetY, Integer(BaseObject), '', 1000);
            1: SendDelayMsg(Self, 3017, NextMagic.GetMagIdx, nTargetX, nTargetY, Integer(BaseObject), '', 1500);
            2: SendDelayMsg(Self, 3017, NextMagic.GetMagIdx, nTargetX, nTargetY, Integer(BaseObject), '', 1500);
            3: SendDelayMsg(Self, 3017, NextMagic.GetMagIdx, nTargetX, nTargetY, Integer(BaseObject), '', 1500);
          end;
        end else if NextMagic = nil then begin
          m_btMagicOrder := 0;
          case m_btJob of
            0: SendDelayMsg(Self, 1653, m_MagicSkills[SKILL_220].MagicInfo.dwCoolDownTime div 1000, SKILL_220, 0, 0, '', 2000);
            1: SendDelayMsg(Self, 1653, m_MagicSkills[SKILL_224].MagicInfo.dwCoolDownTime div 1000, SKILL_224, 0, 0, '', 2000);
            2: SendDelayMsg(Self, 1653, m_MagicSkills[SKILL_228].MagicInfo.dwCoolDownTime div 1000, SKILL_228, 0, 0, '', 2000);
            3: SendDelayMsg(Self, 1653, m_MagicSkills[SKILL_232].MagicInfo.dwCoolDownTime div 1000, SKILL_232, 0, 0, '', 2000);
          end;
          SendRefMsg(RM_510, m_nCurrX, m_nCurrY, 321, 0, '');
        end;
      end;   }

    end;
  end;
end;

//拆分物品

procedure TPlayObject.ClientSplitItem(nMakeIndex: Integer; nCount: Integer; boScript: Boolean);
var
  SplitItem, UserItem                   : pTUserItem;
  StdItem                               : pTStdItem;
begin
  if m_boDeath or m_boGhost then Exit;
  if (nMakeIndex <= 0) or (nCount <= 0) then Exit;

  if GetUserItemByMakeIndex(nMakeIndex, UserItem) >= 0 then begin
    if (UserItem <> nil) then
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
  end else
    Exit;

  if (UserItem <> nil) and (StdItem <> nil) then begin
    //脚本拆分物品
    if boScript then begin
      if (TNormNpc(m_SMELTNPC) <> nil) and
        IsEnvir(TNormNpc(m_SMELTNPC).m_PEnvir) and
        ((abs(TNormNpc(m_SMELTNPC).m_nCurrX - m_nCurrX) < 15) and
        (abs(TNormNpc(m_SMELTNPC).m_nCurrY - m_nCurrY) < 15)) or
        (TNormNpc(m_SMELTNPC).m_boIsHide) then begin
        m_sScriptParam[0] := IntToStr(nMakeIndex);                                                  //IDX
        m_sScriptParam[1] := StdItem.Name;
        m_sScriptParam[2] := IntToStr(nCount);                                                      //数量
        TNormNpc(m_SMELTNPC).GotoLable(Self, m_sNextLabel, False);
      end;
    end else begin
      //只有支持自动叠加的物品才支持拆分
      if IsEnoughBag then begin
        if CheckSPCode(StdItem.Reserved, RE_ALLOWPILE) then begin
          if (UserItem.Dura > nCount) then begin

            New(SplitItem);
            if UserEngine.CopyToUserItemFromName(StdItem.Name, SplitItem) then begin
              SplitItem^.Dura := nCount;
              SplitItem^.DuraMax := StdItem.DuraMax;
              //检测绑定
              if (UserItem.btItemExt[4] = 1) then SplitItem^.btItemExt[4] := 1;
              Dec(UserItem.Dura, nCount);
              SendUpdateItem(UserItem);

              AddItemToBag(SplitItem);
              SendAddItem(SplitItem);

              if StdItem.boGameLog = 1 then
                AddGameDataLog('9' + #9 +
                  m_sMapName + #9 +
                  IntToStr(m_nCurrX) + #9 +
                  IntToStr(m_nCurrY) + #9 +
                  m_sCharName + #9 +
                  StdItem.Name + #9 +
                  IntToStr(UserItem.MakeIndex) + #9 +
                  IntToStr(SplitItem.MakeIndex) + #9 +
                  IntToStr(nCount));
            end else
              Dispose(SplitItem);
          end;
        end;
      end else begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '包裹空间不够!!!');
      end;
    end;
  end;
end;

//存物品到宠物

procedure TPlayObject.ClientStorageItemToPetBag(nItemIdx: Integer);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  bo19                                  : Boolean;
  StdItem                               : pTStdItem;
begin
  if (m_PetInfo[0].nMakeIndex = 0) and (m_PetInfo[1].nMakeIndex = 0) and
    (m_PetInfo[2].nMakeIndex = 0) and (m_PetInfo[3].nMakeIndex = 0) and
    (m_PetInfo[4].nMakeIndex = 0) and (m_PetInfo[5].nMakeIndex = 0) then begin
    SendDefMessage(SM_9604, Integer(Self), 0, 0, 0, '');
    SysMsg('你没有宠物,无法使用本功能。', c_Red, t_Hint);
    Exit;
  end;

  //检查宠物包裹是否已经满了
  if m_PetItemList.Count >= m_nPetBagSize then begin
    SendDefMessage(SM_9604, Integer(Self), 0, 0, 0, '');
    SysMsg('宠物包裹已经满了,无法放入更多的东西。', c_Red, t_Hint);
    Exit;
  end;

  bo19 := False;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if (UserItem.MakeIndex = nItemIdx) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        {物品控制,禁止放入宠物包裹}
        if CheckSPCode(StdItem.SPCode, SP_DISABLEINPETBAG) then begin
          SysMsg(StdItem.FilterName + '不允许放入宠物包裹', c_Red, t_Hint);
          bo19 := False;
          Break;
        end;

        //魂佑灵兽禁止放入宠物包裹
        if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
          bo19 := False;
          Break;
        end;

        {已放出豹禁止放入宠物包裹}
        if IsDownPetItem(UserItem.MakeIndex) then begin
          bo19 := False;
          Break;
        end;

        m_PetItemList.Add(UserItem);
        m_ItemList.Delete(i);
        WeightChanged();
        SendDefMessage(SM_9604, 0, 0, 0, 1, '');
        SendAddPetItem(UserItem);
        bo19 := True;
        Break;
      end;
    end;
  end;
  if not bo19 then
    SendDefMessage(SM_9604, Integer(Self), 0, 0, 0, '');
end;

procedure TPlayObject.CheckStoreBagDupeItem;
var
  i, ii                                 : Integer;
  UserItem, UserItem1                   : pTUserItem;
  StdItem                               : pTStdItem;
  s14                                   : string;
begin
    //检查背包中是否有复制品
  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem = nil then Continue;
    if StdItem = nil then begin
{$IF USESDK = DEBUG}
      SysMsg('删除非法物品:' + IntToStr(UserItem.MakeIndex), c_Pink, t_Hint);
{$IFEND}
      m_ItemList.Delete(i);
      Dispose(UserItem);
      Continue;
    end;

    s14 := StdItem.Name;
    for ii := i - 1 downto 0 do begin
      UserItem1 := m_ItemList.Items[ii];
      if (UserItem.MakeIndex = UserItem1.MakeIndex) and (UserEngine.GetStdItemName(UserItem1.wIndex) = s14) then begin
{$IF USESDK = DEBUG}
        SysMsg('删除复制品:' + IntToStr(UserItem.MakeIndex), c_Pink, t_Hint);
{$IFEND}
        m_ItemList.Delete(ii);
        Dispose(UserItem1);
        Break;
      end;
    end;
      //检查背包物品和身上装备是否有复制
    for ii := Low(THumItems) to High(THumItems) do begin
      if (m_UseItems[ii].wIndex > 0) and (UserItem.MakeIndex = m_UseItems[ii].MakeIndex) and (UserEngine.GetStdItemName(m_UseItems[ii].wIndex) = s14) then begin
{$IF USESDK = DEBUG}
        SysMsg('删除复制品:' + IntToStr(m_UseItems[ii].MakeIndex), c_Pink, t_Hint);
{$IFEND}
        m_UseItems[ii].wIndex := 0;
        Break;
      end;
    end;
  end;
end;

procedure TPlayObject.ClientStorageItem(NPC: TObject; nItemIdx: Integer; boFast:
  Boolean; sMsg: string);
var
  Merchant                              : TMerchant;
  i                                     : Integer;
  UserItem                              : pTUserItem;
  bo19                                  : Boolean;
  StdItem                               : pTStdItem;
  sName                                 : string;
  StdItem80                             : TStdItem;
begin
  bo19 := False;
  UserItem := nil;

  if (m_wShopItemCount > 0) or m_boArrow or (not m_boCanGetBackItem) then begin
    SysMsg('您现在不可以使用仓库功能!!!', c_Red, t_Hint);
    Exit;
  end;

  if (m_nPayMent = 1) and not g_Config.boTryModeUseStorage then begin
    SysMsg(g_sTryModeCanotUseStorage {'试玩模式不可以使用仓库功能!!!'}, c_Red, t_Hint);
    Exit;
  end;

  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];

    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem = nil then Break;
    StdItem80 := StdItem^;
    {取自定义物品名称}
    sName := '';
    ItemUnit.GetCustomItemName(UserItem, sName);

    if (UserItem.MakeIndex = nItemIdx) and CompareLStr(sName, sMsg, Length(sMsg)) then begin
      {物品控制-禁止存仓物品}
      if CheckSPCode(StdItem.SPCode, SP_DISABLESTORAGE) then begin
        SendDefMessage(38288, 1, 255, 0, 0, sName + ' 不允许放入仓库。');
        Break;
      end;

      {魂佑灵兽禁止存仓}
      if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
        SendDefMessage(38288, 1, 255, 0, 0, '魂佑灵兽石不允许保存。');
        Break;
      end;

      {已放出豹禁止存仓}
      if IsDownPetItem(UserItem.MakeIndex) then begin
        SendDefMessage(38288, 1, 255, 0, 0, sName + ' 放出宠物时不允许保存。');
        Break;
      end;

      Merchant := UserEngine.FindMerchant(NPC);
      if (Merchant <> nil) and
        (Merchant.m_boStorage) and                                                                  {检查NPC是否允许存物品}
        ((IsEnvir(Merchant.m_PEnvir) and
        (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
        (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) or (Merchant = g_FunctionNPC)) then begin
        if m_StorageItemList.Count < m_btStorageSize {49} then begin
          m_StorageItemList.Add(UserItem);
          m_ItemList.Delete(i);
          WeightChanged();
          {快捷存取}
          if boFast then begin
            m_defMsg := MakeDefaultMsg(3039, Integer(NPC), 1, 2, 0);

            if Assigned(m_VersionManage) then
            try
              SendSocket(@m_defMsg, m_VersionManage.OnGetClientItemToMsg(Self, UserItem));
            except
              MainOutMessage(Format('TPlayObject::OnGetClientItemToMsg SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
            end;

          end else
            SendDefMessage(SM_STORAGE_OK, 0, 0, 0, 0, '');

          //记录日志
          if StdItem.boGameLog = 1 then
            AddGameDataLog('1' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              '0');
        end else begin
          SendDefMessage(SM_STORAGE_FULL, 0, 0, 0, 0, '');                                          {仓库满了}
        end;
        bo19 := True;
      end;
      Break;
    end;
  end;
  CheckStoreBagDupeItem;                                                                            //检测重复id
  if not bo19 then
    SendDefMessage(SM_STORAGE_FAIL, 0, 0, 0, 0, '');
end;

//取回宠物包裹中的物品

procedure TPlayObject.ClientTakebackPetItem(nItemIdx: Integer);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  bo19                                  : Boolean;
  StdItem                               : pTStdItem;
begin
  bo19 := False;
  UserItem := nil;
  if (m_PetInfo[0].nMakeIndex = 0) and (m_PetInfo[1].nMakeIndex = 0) and
    (m_PetInfo[2].nMakeIndex = 0) and (m_PetInfo[3].nMakeIndex = 0) and
    (m_PetInfo[4].nMakeIndex = 0) and (m_PetInfo[5].nMakeIndex = 0) then begin
    SendDefMessage(SM_9604, Integer(Self), 0, 0, 0, '');
    SendDefMessage(618, nItemIdx, 1, 0, 0, '');
    SysMsg('你没有宠物,无法使用本功能。', c_Red, t_Hint);
    Exit;
  end;

  for i := m_PetItemList.Count - 1 downto 0 do begin
    UserItem := m_PetItemList.Items[i];

    if (UserItem.MakeIndex = nItemIdx) then begin
      if (IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex))) then begin
        if AddItemToBag(UserItem) then begin
          SendDefMessage(SM_9605, Integer(Self), 0, 0, 1, '');
          SendAddItem(UserItem);
          m_PetItemList.Delete(i);
          SendDefMessage(SM_TAKEBACKSTORAGEITEM_OK, nItemIdx, 0, 0, 0, '');
          bo19 := True;
        end else begin
          SendDefMessage(SM_TAKEBACKSTORAGEITEM_FULLBAG, 0, 0, 0, 0, '');
        end;
      end else begin
        SysMsg(g_sCanotGetItems {'无法携带更多的东西!!!'}, c_Red,
          t_Hint);
      end;
      Break;
    end;
  end;
  if not bo19 then begin
    SendDefMessage(SM_9605, 0, 0, 0, 0, '');
    SendDefMessage(SM_TAKEBACKSTORAGEITEM_FAIL, 0, 0, 0, 0, '');
  end;
end;

procedure TPlayObject.ClientTakeBackStorageItem(NPC: TObject; nItemIdx: Integer;
  boFast: Boolean; sMsg: string);                                                                   //004DC664
var
  Merchant                              : TMerchant;
  i                                     : Integer;
  UserItem                              : pTUserItem;
  bo19                                  : Boolean;
  StdItem                               : pTStdItem;
  sName                                 : string;
begin
  bo19 := False;
  UserItem := nil;
  Merchant := UserEngine.FindMerchant(NPC);
  if Merchant = nil then Exit;

  if (m_wShopItemCount > 0) or m_boArrow then begin
    SysMsg('您现在不可以使用仓库功能!!!', c_Red, t_Hint);
    Exit;
  end;

  if (m_nPayMent = 1) and not g_Config.boTryModeUseStorage then begin
    SysMsg(g_sTryModeCanotUseStorage {'试玩模式不可以使用仓库功能!!!'}, c_Red, t_Hint);
    Exit;
  end;
  if not m_boCanGetBackItem then begin
    if m_boPasswordLocked then begin
      if not ExecuteScript(g_FunctionNPC, '@仓库锁定') then
        SendMsg(Merchant, RM_MENU_OK, 0, Integer(Self), 0, 0,
          g_sStorageIsLockedMsg + #13#10#13#10
          + '仓库开锁命令: @' + g_GameCommand.UNLOCKSTORAGE.sCmd + #13#10
          + '仓库加锁命令: @' + g_GameCommand.Lock.sCmd + #13#10
          + '设置密码命令: @' + g_GameCommand.SETPASSWORD.sCmd + #13#10
          + '修改密码命令: @' + g_GameCommand.CHGPASSWORD.sCmd);
    end;
    Exit;
  end;

  for i := m_StorageItemList.Count - 1 downto 0 do begin
    UserItem := m_StorageItemList.Items[i];

    //取自定义物品名称
    sName := '';
    ItemUnit.GetCustomItemName(UserItem, sName);

    if (UserItem.MakeIndex = nItemIdx) and (CompareText(sMsg, sName) = 0) then begin

      if (IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex))) then begin
        if (Merchant <> nil) and
          (Merchant.m_boGetback) and                                                                //检查NPC是否允许取物品
          ((IsEnvir(Merchant.m_PEnvir) and
          (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
          (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) or (Merchant = g_FunctionNPC)) then begin

          if AddItemToBag(UserItem) then begin
            SendAddItem(UserItem);
            m_StorageItemList.Delete(i);
            if boFast then begin
              SendDefMessage(3039, nItemIdx, 1, 3, 0, '');
            end else
              SendDefMessage(SM_TAKEBACKSTORAGEITEM_OK, nItemIdx, 0, 0, 0, '');
            StdItem := UserEngine.GetStdItem(UserItem.wIndex);
            if StdItem.boGameLog = 1 then
              AddGameDataLog('0' + #9 +
                m_sMapName + #9 +
                IntToStr(m_nCurrX) + #9 +
                IntToStr(m_nCurrY) + #9 +
                m_sCharName + #9 +
                StdItem.Name + #9 +
                IntToStr(UserItem.MakeIndex) + #9 +
                '1' + #9 +
                '0');
            m_sScriptParam[0] := StdItem.Name;
            m_sScriptParam[1] := IntToStr(UserItem.MakeIndex);
            ExecuteScript(g_FunctionNPC, '@仓库取物品');
          end else begin
            SendDefMessage(SM_TAKEBACKSTORAGEITEM_FULLBAG, 0, 0, 0, 0, '');
          end;
          bo19 := True;
        end;
      end else begin
        SysMsg(g_sCanotGetItems {'无法携带更多的东西!!!'}, c_Red, t_Hint);
      end;
      Break;
    end;
  end;
  if not bo19 then SendDefMessage(SM_TAKEBACKSTORAGEITEM_FAIL, 0, 0, 0, 0, '');
end;

procedure TPlayObject.ClientTakeItemOutTreasureBox(nItemID: Integer);
var
  i, ii                                 : Integer;
  tm                                    : DWORD;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  if m_TreasureBoxItem = nil then Exit;
  tm := MakeLong(MakeWord(m_TreasureBoxItem.btValue[4], m_TreasureBoxItem.btValue[5]), MakeWord(m_TreasureBoxItem.btValue[6], m_TreasureBoxItem.btValue[7]));
  if (tm < DateTimeToWolTimeEx(Now)) and (tm <> 0) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sNeedInjectPower);
    Exit;
  end;
  for i := m_TreasureBoxItemList.Count - 1 downto 0 do begin
    UserItem := m_TreasureBoxItemList.Items[i];
    if (UserItem <> nil) and (UserItem.MakeIndex = nItemID) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem = nil then Break;
      if IsEnoughBag and IsAddWeightAvailable(UserEngine.GetStdItemWeight(UserItem.wIndex)) then begin
        m_TreasureBoxItemList.Delete(i);
        SendDefMessage(CM_TREASUREBOX, nItemID, 2, 0, 0, '');
        m_ItemList.Add(UserItem);
        SendAddItem(UserItem);
        WeightChanged();
      end else begin
        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
        SysMsg('包裹空间或者负重不够!!!', c_Red, t_Hint);
      end;
      Break;
    end;
  end;
end;

procedure TPlayObject.ClientTakeItemToTreasureBox(nItemID: Integer);
var
  i, ii                                 : Integer;
  tm                                    : DWORD;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  if m_TreasureBoxItem = nil then Exit;
  if (m_TreasureBoxItemList.Count >= m_TreasureBoxItem.DuraMax) then begin
    SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你的灵犀宝盒空间已满,不能存放更多物品');
    Exit;
  end;

  tm := MakeLong(MakeWord(m_TreasureBoxItem.btValue[4], m_TreasureBoxItem.btValue[5]), MakeWord(m_TreasureBoxItem.btValue[6], m_TreasureBoxItem.btValue[7]));
  if (tm < DateTimeToWolTimeEx(Now)) and (tm <> 0) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sNeedInjectPower);
    Exit;
  end;
  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];
    if (UserItem <> nil) and (UserItem.MakeIndex = nItemID) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem = nil then Break;
      {物品控制-禁止放入灵犀宝盒}
      if CheckSPCode(StdItem.SPCode, SP_DISABLEGINREASUREBOX) then begin
        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, Format(sCanNotInTreasureBox, [StdItem.Name]));
        Break;
      end;

      //魂佑灵兽禁止放入灵犀宝盒
      if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
        Exit;
      end;

      {已放出豹禁止放入灵犀}
      if IsDownPetItem(UserItem.MakeIndex) then begin
        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
        Exit;
      end;
      m_ItemList.Delete(i);
      m_TreasureBoxItemList.Add(UserItem);
      SendDefMessage(CM_TREASUREBOX, nItemID, 3, 0, 0, '');
      WeightChanged();
      Break;
    end;
  end;
end;

//取下装备

procedure TPlayObject.ClientTakeOffItems(btWhere: byte; nItemIdx: Integer; sItemName: string);
var
  N10, i                                : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  sName                                 : string;
  nCheckCode                            : Integer;
label
  FailExit;
begin
  N10 := 0;
  nCheckCode := 0;
  if m_PEnvir.m_MapFlag.boNOTAKEON then begin
    SysMsg('当前地图禁止取下物品!!!', c_Red, t_Hint);
    N10 := -4;
    goto FailExit;
  end;

  if (btWhere = U_RIDEDRESS) or m_boInosculatePneuma then begin
    N10 := -4;
    goto FailExit;
  end;

  if not m_boDealing and (btWhere < MAX_HUMITEM_COUNT) then begin
    if m_UseItems[btWhere].wIndex > 0 then begin
      if m_UseItems[btWhere].MakeIndex = nItemIdx then begin
        StdItem := UserEngine.GetStdItem(m_UseItems[btWhere].wIndex);
        if (StdItem <> nil) then begin
          if (StdItem.StdMode in [15, 19, 20, 21, 22, 23, 24, 26]) then begin
            if (not m_boUserUnLockDurg) and (m_UseItems[btWhere].btValue[10] <> 0) then begin
              SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
              N10 := -4;
              goto FailExit;
            end;
          end;

          //物品控制-禁止取下物品
          if CheckSPCode(StdItem.SPCode, SP_DISABLETAKEOFF) then begin
            SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
            N10 := -4;
            goto FailExit;
          end;

          //取下的是马牌
          try
            if (StdItem.StdMode = 33) then begin
              nCheckCode := 1;
              if m_Horse <> nil then begin                                                          //下马状态
                HorseHide;
                if m_PEnvir.m_MapFlag.boRideOn then
                  SysMsg('你的' + HorseName + '已被收起', c_Red, t_Hint);
              end else begin                                                                        //在马上,或者这个地图不能骑马
                if m_PEnvir.m_MapFlag.boRideOn and (HorseName <> '') then
                  SysMsg('你的' + HorseName + '已被收起', c_Red, t_Hint);
              end;
              m_btHorseType := 0;
              HorseName := '';
              if m_boRideOn and (m_PetInfo[2].nMakeIndex = 0) then m_boRideOn := False;             //本体骑乘灵兽
            end;
            //虎王盾
            if (StdItem.StdMode = 12) and (StdItem.Shape in [61..72]) and (m_Tiger <> nil) then begin
              ClientReCallTiger;
            end;
          except

          end;
          //取自定义物品名称
          sName := '';
          ItemUnit.GetCustomItemName(@m_UseItems[btWhere], sName);

          if (CompareText(sItemName, sName) = 0) then begin
            New(UserItem);
            UserItem^ := m_UseItems[btWhere];
            if AddItemToBag(UserItem) then begin
              m_UseItems[btWhere].wIndex := 0;
              //取下装备触发脚本

              SendAddItem(UserItem);
              SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
              RecalcAbilitys(True);
              SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
              SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

              //刷新镶嵌玉石的属性
              if (btWhere in [U_NECKLACE..U_BELT]) and (StdItem.StdItemAdd.btHole > 0) and
                (m_UseItems[btWhere]).IsGem then begin
                RecalcGemSacredDam();
              end;

              m_sScriptParam[0] := StdItem.Name;
              m_sScriptParam[1] := StdItem.FilterName;
              m_sScriptParam[2] := IntToStr(btWhere);
              if not ExecuteScript(g_FunctionNPC, '@TakeOff' + IntToStr(btWhere)) then
                ExecuteScript(g_FunctionNPC, '@TakeOffAll');
              if btWhere = 0 then begin
                m_nMagicStatus := GetMagicStatus;
                Status2Changed;
              end;
              FeatureChanged();
            end else begin
              Dispose(UserItem);
              N10 := -3;
            end;
          end;
        end;
      end;
    end else N10 := -2;
  end else N10 := -1;

  FailExit:
  if N10 <= 0 then
    SendDefMessage(SM_TAKEOFF_FAIL, N10, 0, 0, 0, '');
end;

//装备物品                                             MakeIndex

function TPlayObject.ClientTakeOnItems(btWhere: byte; nItemIdx: Integer; sItemName: string; boFlag: Boolean): Boolean; //004DAC70
var
  i, n14, n18, j                        : Integer;
  UserItem, TakeoffItem                 : pTUserItem;
  StdItem, StdItem20                    : pTStdItem;
  StdItem58                             : TStdItem;
  sName                                 : string;
  boCanTakeOn, boSacredBelt             : Boolean;
label
  FailExit;
begin
  StdItem := nil;
  UserItem := nil;
  Result := False;
  n14 := -1;
  if m_PEnvir.m_MapFlag.boNOTAKEON then begin
    SysMsg('当前地图禁止穿戴物品!!!', c_Red, t_Hint);
    n18 := -1;
    goto FailExit;
  end;

  if (btWhere = U_RIDEDRESS) or m_boInosculatePneuma then begin
    n18 := -1;
    goto FailExit;
  end;

  if m_boPneuma then begin
    //灵珠状态下不能使用武器
    if (btWhere = U_WEAPON) and m_boPneumaEffMode then begin
      n18 := -1;
      goto FailExit;
    end;
  end;

  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];                                                                //包裹里的物品
    if (UserItem <> nil) and (UserItem.MakeIndex = nItemIdx) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        sName := '';
        ItemUnit.GetCustomItemName(UserItem, sName);
        if (CompareText(sItemName, sName) = 0) then begin
          n14 := i;
          Break;
        end;
      end;
    end;
    UserItem := nil;
  end;

  n18 := 0;
  if (StdItem <> nil) and (UserItem <> nil) then begin
    if CheckUserItems(btWhere, StdItem) then begin
      //物品控制-禁止元神、红名、本体穿戴
      if m_boPneuma then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEPNEUMATAKEON))
      else if (PKLevel > 2) then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEREDTAKEON))
      else
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEHUMANTAKEON));

      if boCanTakeOn then begin
        case StdItem.NeedRace of
          1: begin
              if m_btJob < 3 then begin
                boCanTakeOn := False;
              {此物品仅支持妖士佩戴!!!}
              end;
            end;
          3: begin
              if m_btJob <> 0 then begin
                boCanTakeOn := False;
              {此物品仅支持战士佩戴!!!}
              end;
            end;
          4: begin
              if m_btJob <> 1 then begin
                boCanTakeOn := False;
              {此物品仅支持法师佩戴!!!}
              end;
            end;
          5: begin
              if m_btJob <> 2 then begin
                boCanTakeOn := False;
              {此物品仅支持道士佩戴!!!}
              end;
            end;
          6: begin
              if (m_btJob <> 0) and (m_btJob <> 1) then begin
                boCanTakeOn := False;
              {此物品仅支持战士、法师佩戴!!!}
              end;
            end;
          7: begin
              if (m_btJob <> 0) and (m_btJob <> 2) then begin
                boCanTakeOn := False;
              {此物品仅支持战士、道士佩戴!!!}
              end;
            end;
          8: begin
              if (m_btJob <> 0) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持战士、妖士佩戴!!!}
              end;
            end;
          9: begin
              if (m_btJob <> 1) and (m_btJob <> 2) then begin
                boCanTakeOn := False;
              {此物品仅支持法师、道士佩戴!!!}
              end;
            end;
          10: begin
              if (m_btJob <> 1) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持法师、妖士佩戴!!!}
              end;
            end;
          11: begin
              if (m_btJob <> 2) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持道士、妖士佩戴!!!}
              end;
            end;
          12: begin
              if (m_btJob <> 1) and (m_btJob <> 2) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持法师、道士、妖士佩戴!!!}
              end;
            end;
          13: begin
              if (m_btJob <> 0) and (m_btJob <> 2) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持战士、道士、妖士佩戴!!!}
              end;
            end;
          14: begin
              if (m_btJob <> 0) and (m_btJob <> 1) and (m_btJob <> 3) then begin
                boCanTakeOn := False;
              {此物品仅支持战士、法师、妖士佩戴!!!}
              end;
            end;
        end;
      end;
      if not boCanTakeOn then begin
        SysMsg('你不能佩戴此物品!!!', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;
      //马牌检测
      if (StdItem.StdMode = 33) and (m_btHorseType <> 0) then begin
        n18 := -1;
      end;

      if m_boPneuma then begin
        //破碎装备不能佩戴
        if (UserItem.btItemExt[4] = 4) and (UserItem.Dura <= 0) then begin
          n18 := -1;
          goto FailExit;
        end;
      end;

      StdItem58 := StdItem^;
      ItemUnit.GetItemAddValue(UserItem, StdItem58);
      if (n18 = 0) and CheckTakeOnItems(btWhere, StdItem58) and CheckItemBindUse(UserItem) then begin
        TakeoffItem := nil;
        if btWhere in [0..MAX_HUMITEM_COUNT - 1] then begin
          //取下物品
          if m_UseItems[btWhere].wIndex > 0 then begin                                              //当前位置已装备了物品,则取下
            StdItem20 := UserEngine.GetStdItem(m_UseItems[btWhere].wIndex);
            if (StdItem20 <> nil) then begin
              if (StdItem20.StdMode in [15, 19, 20, 21, 22, 23, 24, 26]) then begin                 //神秘物品
                if (not m_boUserUnLockDurg) and (m_UseItems[btWhere].btValue[10] <> 0) then begin
                  SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                  n18 := -4;
                  goto FailExit;
                end;
              end;
              if not m_boUserUnLockDurg and ((StdItem20.Reserved and 2) <> 0) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;                                                                                  //004DAE78
              if (StdItem20.Reserved and 4) <> 0 then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
              //物品控制-禁止取下物品
              if CheckSPCode(StdItem20.SPCode, SP_DISABLETAKEOFF) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
              if StdItem20.StdMode = 33 then begin                                                  //取下马牌
                HorseHide;
                if m_boRideOn and (m_PetInfo[2].nMakeIndex = 0) then begin
                  m_boRideOn := False;
                end;
                if m_PEnvir.m_MapFlag.boRideOn then
                  SysMsg('你的' + HorseName + '被收起', c_Red, t_Hint);                             //只有可以骑马的地图才提示
              end;
              HorseName := '';
              //虎王盾
              if (StdItem.StdMode = 12) and (StdItem.Shape in [61..72]) and (m_Tiger <> nil) then begin
                ClientReCallTiger;
              end;

            end;
            New(TakeoffItem);
            TakeoffItem^ := m_UseItems[btWhere];
            //取下装备触发脚本
            if (TakeoffItem <> nil) then begin
              m_sScriptParam[0] := StdItem20.Name;
              m_sScriptParam[1] := StdItem20.FilterName;
              m_sScriptParam[2] := IntToStr(btWhere);
              if not ExecuteScript(g_FunctionNPC, '@TakeOff' + IntToStr(btWhere)) then
                ExecuteScript(g_FunctionNPC, '@TakeOffAll');
            end;
          end;

          if (StdItem58.StdMode in [15, 19, 20, 21, 22, 23, 24, 26]) then begin
            if StdItem.Shape in [130, 131, 132] then begin
              if (UserItem.btValue[14] <> 0) then
                UserItem.btValue[14] := 0;
              SendUpdateItem(UserItem);
            end;
          end;

          m_UseItems[btWhere] := UserItem^;

          DelBagItem(n14);
          boCanTakeOn := False;
          if TakeoffItem <> nil then begin
            AddItemToBag(TakeoffItem);
            SendAddItem(TakeoffItem);
            if TakeoffItem^.IsGem then
              boCanTakeOn := True;
          end;

          //马牌的处理:装上马牌
          if StdItem.StdMode = 33 then begin
            //取得马的名字
            m_btHorseType := StdItem.Shape;
            if m_btHorseType = 0 then begin
              m_btHorseType := UserItem.btValue[0];
              HorseName := UserEngine.GetHorseName(UserItem);
            end else begin
              HorseName := StdItem.Name;
              ArrestStringEx(StdItem.Name, '(', ')', HorseName);
            end;
            if m_btHorseType in [51..60] then Dec(m_btHorseType, 50);
            //地图允许骑马,则生成马
            if not boFlag then begin
              //扣持久
              m_UseItems[btWhere].Dura := m_UseItems[btWhere].Dura - 500;

              if m_UseItems[btWhere].Dura <= 0 then begin
                SendDelItems(@m_UseItems[btWhere]);
                m_UseItems[btWhere].wIndex := 0;
              end else
                SendMsg(Self, RM_DURACHANGE, btWhere, m_UseItems[btWhere].Dura, m_UseItems[btWhere].DuraMax, 0, '');

              if (m_UseItems[btWhere].wIndex > 0) and (m_btHorseType > 0) and (HorseName <> '') then begin
                if (m_PEnvir.m_MapFlag.boRideOn) then begin
                  m_Horse := MakeSlave(HorseName, 7, 7, 100, 24 * 60 * 60, -1);
                  if m_Horse <> nil then begin
                    m_Horse.TurnTo(m_btDirection);
                    SysMsg('你的' + HorseName + '被放出', c_Red, t_Hint);
                    SendDefMessage(34977, m_Horse.m_wAppr, 612, 1, 0, '');
                  end else
                    SysMsg('释放马失败', c_Red, t_Hint);
                end else begin
                  m_Horse := nil;
                  if m_UseItems[btWhere].wIndex > 0 then
                    SysMsg('本地图不允许骑宠', c_Red, t_Hint);
                end;
              end;
            end else
              SendMsg(Self, RM_TAKEON2, btWhere, m_UseItems[btWhere].MakeIndex, 0, 0, '');
            {超级技能项链}
          end else if StdItem.StdMode = 18 then begin
            if CheckUserItemTimeOut(@m_UseItems[btWhere], StdItem) then begin
              m_UseItems[btWhere].wIndex := 0;
              SendDelItems(@m_UseItems[btWhere]);
              SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              n18 := -1;
              goto FailExit;
            end;
            {灵鼠神佑、金牛神佑}
          end else if StdItem.StdMode = 29 then begin
            if CheckUserItemTimeOut(@m_UseItems[btWhere], StdItem) then begin
              m_UseItems[btWhere].wIndex := 0;
              SendDelItems(@m_UseItems[btWhere]);
              SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              n18 := -1;
              goto FailExit;
            end;
          end else if (StdItem.StdMode = 6) and (StdItem.Shape = 20) then begin
            if CheckUserItemTimeOut(@m_UseItems[btWhere], StdItem) then begin
              m_UseItems[btWhere].wIndex := 0;
              SendDelItems(@m_UseItems[btWhere]);
              SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              n18 := -1;
              goto FailExit;
            end;
          end;

          //检查要装备的物品是否已经附魔

          if (m_UseItems[btWhere].Evil.MakeIndex <> 0) and (m_UseItems[btWhere].Evil.sName <> '') then begin
            if not m_boPneuma then                                                                  //人物穿戴
              SysMsg('主体佩带附魔装备,不能发挥出附魔属性的威力,请将附魔装备给元神佩带!', c_Red, t_Hint)
          end;
          boSacredBelt := m_boSacredBelt;
          RecalcAbilitys(True);
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
          SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

          //刷新镶嵌玉石的属性
          if (btWhere in [U_NECKLACE..U_BELT]) and
            (((StdItem.StdItemAdd.btHole > 0) and (m_UseItems[btWhere]).IsGem) or boCanTakeOn) then begin
            RecalcGemSacredDam();
          end;

          //神圣腰带
          if m_boSacredBelt and (not boSacredBelt) then
            SendDefMessage(SM_HOLYBELT, Integer(Self), 3, 0, 0, '');

          //穿上装备触发脚本

          m_sScriptParam[0] := StdItem.Name;
          m_sScriptParam[1] := StdItem.FilterName;
          m_sScriptParam[2] := IntToStr(btWhere);
          if not ExecuteScript(g_FunctionNPC, '@TakeOn' + IntToStr(btWhere)) then
            ExecuteScript(g_FunctionNPC, '@TakeOnAll');

          if btWhere = 0 then begin
            if m_UseItems[btWhere].btValue[10] = 0 then begin
              m_UseItems[btWhere].btValue[14] := Random(16);
              m_UseItems[btWhere].btValue[10] := 1;
            end;
            m_nMagicStatus := GetMagicStatus;
            Status2Changed;
          end;
          n18 := 1;
          FeatureChanged();
          SendDefMessage(SM_TAKEON_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');

          if m_UseItems[btWhere].IsGod() then begin
            if (StdItem58.StdMode = 5) then begin
              if m_UseItems[btWhere].btItemExt[20] >= 100 then begin
                Dec(m_UseItems[btWhere].btItemExt[20], _Max(m_UseItems[btWhere].btValue[19], 1));
              end;
              m_UseItems[btWhere].btValue[15] := 0;
              m_UseItems[btWhere].btValue[17] := 0;
              SendDelayMsg(Self, RM_SENDGODUSEVAL, 0, m_UseItems[btWhere].btItemExt[20], 0, 0, '', 500);
            end else if (StdItem58.StdMode in [10, 11]) then
              SendDelayMsg(Self, RM_SENDGODUSEVAL, 1, m_UseItems[btWhere].btValue[15], 0, 0, '', 500);
          end;
          Result := True;
        end;
      end else n18 := -1;
    end else n18 := -1;
  end;
  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEON_FAIL, n18, 0, 0, 0, '');
end;

procedure TPlayObject.ClientTakeOnTigerItem(nWhere, nMakeIndex: Integer);
var
  n18, n14, i                           : Integer;
  StdItem                               : pTStdItem;
  UserItem, TakeoffItem                 : pTUserItem;
  sName                                 : string;
  StdItem18                             : TStdItem;
label
  FailExit;
begin
  if m_boPneuma then Exit;
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王盾的

  StdItem := nil;
  UserItem := nil;
  n14 := -1;
  n18 := 0;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];                                                                //包裹里的物品
    if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        n14 := i;
        Break;
      end;
    end;
    UserItem := nil;
  end;

  if (m_Tiger <> nil) and (StdItem <> nil) and (UserItem <> nil) then begin
    if CheckTigerUserItems(nWhere, StdItem) then begin
      StdItem18 := StdItem^;

      if (m_TorDDM.Tiger.DB.Dragon <> StdItem18.Shape) then begin
        if StdItem18.Shape = 0 then
          SysMsg('请先招出虎王', c_Red, t_Hint)
        else
          SysMsg('请先招出龙王', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;

      if (m_TorDDM.Tiger.DB.level < StdItem18.NeedLevel) then begin
        SysMsg('等级不满足条件,无法佩戴。', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;

      TakeoffItem := nil;
      if nWhere in [0..MAX_TIGER_ITEM_COUNT - 1] then begin
        //取下物品
        if m_TorDDM.Tiger.Items[nWhere].wIndex > 0 then begin
          New(TakeoffItem);
          TakeoffItem^ := m_TorDDM.Tiger.Items[nWhere];
        end;
        m_TorDDM.Tiger.Items[nWhere] := UserItem^;
        DelBagItem(n14);
        if TakeoffItem <> nil then begin
          AddItemToBag(TakeoffItem);
          SendAddItem(TakeoffItem);
        end;
        n18 := 1;
        SendDefMessage(SM_TAKETIGER_OK, 1, 1, 0, 0, '');
        RecalcTigerAbility;
      end;
    end;
  end;

  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEON_FAIL, n18, 0, 0, 0, '');
end;

procedure TPlayObject.ClientTakeOffTigerItem(nWhere, nMakeIndex: Integer);
var
  n18                                   : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
label
  FailExit;
begin
  if m_boPneuma then Exit;
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王盾的
  n18 := 0;
  if nWhere in [0..MAX_TIGER_ITEM_COUNT - 1] then begin
    if m_TorDDM.Tiger.Items[nWhere].wIndex > 0 then begin
      if m_TorDDM.Tiger.Items[nWhere].MakeIndex = nMakeIndex then begin
        StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[nWhere].wIndex);
        if (StdItem <> nil) then begin
          New(UserItem);
          UserItem^ := m_TorDDM.Tiger.Items[nWhere];
          if AddItemToBag(UserItem) then begin
            m_TorDDM.Tiger.Items[nWhere].wIndex := 0;
            SendAddItem(UserItem);
            SendDefMessage(SM_TAKETIGER_OK, 0, 1, 0, 0, '');
            RecalcTigerAbility;
            n18 := 1;
          end else begin
            Dispose(UserItem);
            n18 := -1;
          end;
        end;
      end;
    end;
  end;

  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEOFF_FAIL, n18, 0, 0, 0, '');
end;

procedure TPlayObject.ClientUPGradeTreasureBox(nCount: Integer; sBuf: string);
var
  i, j, nCode                           : Integer;
  sMsg                                  : string;
  ANpc                                  : TNormNpc;
  buf                                   : array[0..5] of Integer;
  UserItem                              : pTUserItem;
  pUserItems                            : array[0..5] of pTUserItem;
  pStdItems                             : array[0..5] of pTStdItem;
  tm                                    : DWORD;
begin
  if (m_ClickNPC = nil) or (nCount <= 0) or (nCount > 6) then Exit;
  ANpc := TNormNpc(m_ClickNPC);
  FillChar(buf, SizeOf(Integer) * 6, 0);
  DeCodeBuffer(sBuf, @buf[0], SizeOf(Integer) * nCount);
  nCode := 0;

  if (m_TreasureBoxItem = nil) then begin
    nCode := -1;
    sMsg := '你的灵犀宝盒还没有注入灵力,无法强化';
  end;

  if (nCode = 0) then begin
    tm := MakeLong(MakeWord(m_TreasureBoxItem.btValue[4], m_TreasureBoxItem.btValue[5]), MakeWord(m_TreasureBoxItem.btValue[6], m_TreasureBoxItem.btValue[7]));
    if (tm < DateTimeToWolTimeEx(Now)) and (tm <> 0) then begin
      sMsg := '你的灵犀宝盒灵力已经耗尽,无法强化';
      Exit;
    end;
  end;

  if (nCode = 0) then begin
    tm := MakeLong(MakeWord(m_TreasureBoxItem.btValue[4], m_TreasureBoxItem.btValue[5]), MakeWord(m_TreasureBoxItem.btValue[6], m_TreasureBoxItem.btValue[7]));
    if (tm = 0) then begin
      nCode := -1;
      sMsg := '你的灵犀宝盒已经强化,不需要再次强化';
    end;
  end;

  if (nCode = 0) then begin
    for i := 0 to nCount - 1 do begin
      for j := 0 to m_ItemList.Count - 1 do begin
        UserItem := m_ItemList[j];
        if UserItem.MakeIndex = buf[i] then begin
          pUserItems[i] := UserItem;
          pStdItems[i] := UserEngine.GetStdItem(UserItem.wIndex);
          Break;
        end;
      end;
      if ((pUserItems[i] = nil) or (pStdItems[i] = nil)) and (buf[i] <> 0) then begin
        nCode := -1;
        sMsg := '没有在你的包裹中发现强化宝盒所需要的元灵晶石或幸运符';
        Break;
      end;
    end;
  end;
  {函数触发开始}
  if (nCode = 0) then begin
    m_sScriptParam[0] := IntToStr(nCount);
    for i := 0 to nCount - 1 do begin
      if pUserItems[i] <> nil then begin
        m_sScriptParam[i + 1] := IntToStr(pUserItems[i].MakeIndex);
{$IF USESDK = DEBUG}
        SysMsg(Format('物品%d:%d', [i, pUserItems[i].MakeIndex]), c_Pink, t_Hint);
{$IFEND}
      end;
    end;
    if (IsEnvir(ANpc.m_PEnvir) and
      (abs(ANpc.m_nCurrX - m_nCurrX) < 15) and
      (abs(ANpc.m_nCurrY - m_nCurrY) < 15)) or (ANpc.m_boIsHide) then begin
      ANpc.GotoLable(Self, '@强化灵犀宝盒', False);
    end;
  end;
  if (nCode <> 0) and (sMsg <> '') then begin
    SendMsg(ANpc, RM_MERCHANTDLGCLOSE, 0, Integer(ANpc), 0, 0, '');
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sMsg);
  end;
end;

//使用物品

procedure TPlayObject.ClientUseItems(nItemIdx: Integer; sItemName: string; nPackIdx: Integer);
//根据物品名字获得打包后的物品Shape
  function GetBindItemShape(sName: string): Integer;
  var
    i                                   : Integer;
  begin
    Result := -1;
    for i := 0 to g_UnbindList.Count - 1 do begin
      if g_UnbindList.Strings[i] = sName then begin
        Result := Integer(g_UnbindList.Objects[i]);
        Break;
      end;
    end;
  end;
  //叠加物品
  function PileItems(UserItem: pTUserItem; nMakeIndex: Integer; pStd: pTStdItem): Boolean;
  var
    i                                   : Integer;
    PileItem                            : pTUserItem;
    nCount                              : Integer;
  begin
    Result := False;
    //获得要叠加的物品
    nCount := 0;
    for i := 0 to m_ItemList.Count - 1 do begin
      if (pTUserItem(m_ItemList[i]).MakeIndex = nMakeIndex) and
        (pTUserItem(m_ItemList[i]).wIndex = UserItem.wIndex) and (pTUserItem(m_ItemList[i]).Dura > 0) then
      begin
        PileItem := pTUserItem(m_ItemList[i]);
        Result := True;
        Break;
      end;
    end;
    if Result then begin
      //叠加上限检测
      if (UserItem.Dura >= pStd.Stock) or (PileItem.Dura >= pStd.Stock) then begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotPileItemsMsg);
        Result := True;
        Exit;
      end;

      //检测绑定
      if (UserItem.btItemExt[4] = 1) or (PileItem.btItemExt[4] = 1) then begin
        UserItem.btItemExt[4] := 1;
      end;

      //检测持久
      if (UserItem.Dura + PileItem.Dura) > pStd.Stock then begin
        nCount := pStd.Stock - UserItem.Dura;
        Dec(PileItem.Dura, nCount);
        SendUpdateItem(PileItem);
      end else begin
        nCount := PileItem.Dura;
        SendDelItems(PileItem);
        DelBagItem(PileItem.MakeIndex, pStd.Name);
      end;
      Inc(UserItem.Dura, nCount);
      SendUpdateItem(UserItem);
    end;
  end;
  //乾坤袋打包物品

  function PackageItems(nMakeIndex: Integer): Boolean;
  var
    i                                   : Integer;
    UserItem                            : pTUserItem;
    BindItem                            : pTStdItem;
    pStdItem                            : pTStdItem;
    nItemIdx                            : Integer;
    nCount                              : Integer;
    nShape                              : Integer;
  begin
    Result := False;
    //获得要打包的物品名字
    nItemIdx := -1;
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := pTUserItem(m_ItemList[i]);
      if (UserItem.wIndex > 0) and (UserItem.MakeIndex = nMakeIndex) then begin
        pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
        nItemIdx := UserItem.wIndex;
        if pStdItem <> nil then Result := True;
        Break;
      end;
    end;
    if Result then begin                                                                            //如果获得名字,则获得打包后的物品
      nShape := GetBindItemShape(pStdItem.Name);
      BindItem := UserEngine.GetBindItem(nShape);
      if (BindItem = nil) then Result := False;
    end;
    if Result then begin
      //检查要打包的物品数量够不够
      nCount := 0;
      for i := m_ItemList.Count - 1 downto 0 do begin
        UserItem := pTUserItem(m_ItemList[i]);
        if (UserItem.wIndex > 0) and (UserItem.Dura = UserItem.DuraMax) and (UserItem.wIndex = nItemIdx) then Inc(nCount);
      end;
      if nCount < 6 then begin
        SysMsg(pStdItem.FilterName + '数量不足6个,不可被乾坤药袋收纳。', c_Red, t_Hint);
        Result := False;
      end else begin
        //删除6个要打包的物品
        nCount := 0;
        for i := m_ItemList.Count - 1 downto 0 do begin
          UserItem := pTUserItem(m_ItemList[i]);
          if (UserItem.wIndex > 0) and (UserItem.wIndex = nItemIdx) then begin
            SendDelItems(UserItem);
            Dispose(UserItem);
            m_ItemList.Delete(i);
            Inc(nCount);
            if nCount >= 6 then Break;
          end;
        end;
        //给一个打包后的物品
        New(UserItem);
        if UserEngine.CopyToUserItemFromName(BindItem.Name, UserItem) then begin
          m_ItemList.Add(UserItem);
          SendAddItem(UserItem);
        end else begin
          Dispose(UserItem);
          Result := False;
        end;
        WeightChanged;                                                                              //重量改变
      end;
    end else begin
      SysMsg('此物品不可被乾坤药袋收纳', c_Red, t_Hint);
    end;
  end;

  function CheckUserItemTimeOut(UserItem: pTUserItem; StdItem: pTStdItem): Boolean;
  var
    tm, nowtm                           : DWORD;
  begin
    Result := False;
    tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]),
      MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
    if (tm = 0) and (StdItem.Shape <> 53) then begin                                                //第一次使用
      tm := DateTimeToWolTIme(Now);
      UserItem.btValue[0] := LoByte(LoWord(tm));
      UserItem.btValue[1] := HiByte(LoWord(tm));
      UserItem.btValue[2] := LoByte(HiWord(tm));
      UserItem.btValue[3] := HiByte(HiWord(tm));
      UserItem.btItemExt[4] := 1;                                                                   //绑定
      SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
      SendUpdateItem(UserItem);
      case StdItem.Shape of
        1, 2, 3, 4, 22, 51, 52, 53: ;
        61..80: begin
            SysMsg('您开启了小时卡,使用期限:开启后' + IntToStr(UserItem.Dura) + '小时。', c_Red, t_Hint);
          end else begin
          SysMsg('您开启了天数卡,使用期限:开启后' + IntToStr(UserItem.Dura) + '天。', c_Red, t_Hint);
        end;
      end;
    end else begin
      nowtm := DateTimeToWolTIme(Now);
      if (tm + UserItem.Dura * 86400 < nowtm) or
        ((StdItem.Shape in [61..80]) and (tm + UserItem.Dura * 3600 < nowtm)) then begin
        Result := True;
        SysMsg('该物品已经到期', c_Red, t_Hint);
      end;
    end;
  end;
var
  j, n14, i                             : Integer;
  boEatOK, boFind                       : Boolean;
  UserItem, UserItem2                   : pTUserItem;
  ObjList                               : TList;
  StdItem                               : pTStdItem;
  StdItem2                              : pTStdItem;
  StdItem3                              : pTStdItem;
  StdItem24                             : TStdItem;
  UserItem34                            : TUserItem;
  Monster, BaseObject                   : TBaseObject;
  nX, nY, nCode, nCheckCode             : Integer;
  sMAP, sTmp                            : string;
  tm                                    : DWORD;
  TargeList                             : array of Integer;
  UserMagic                             : pTUserMagic;
  Magic                                 : pTMagic;
label
  EAT_END;

resourcestring
  sExceptionMsg                         = 'CM_EAT:: %d 人物:%s,参数:%d,%s,%d';
begin
  nCheckCode := 0;
  boEatOK := False;
  n14 := 0;
  m_nEatItemMakeIndex := 0;
  m_sScriptParam[0] := '';
  m_sScriptParam[1] := '';
  m_sScriptParam[2] := '';
  m_sScriptParam[3] := '';
  m_sScriptParam[4] := '';
  m_sScriptParam[5] := '';
  Monster := nil;
  try
    StdItem := nil;
    if m_boCanUseItem then begin
      if not m_boDeath then begin
        nCheckCode := 1;
        GetUserItemByMakeIndex(nItemIdx, UserItem);
        if (UserItem <> nil) and (UserItem.MakeIndex = nItemIdx) then begin
          UserItem34 := UserItem^;
          nCheckCode := 2;
          StdItem := UserEngine.GetStdItem(UserItem34.wIndex);
          if StdItem <> nil then begin                                                              //物品存在
            m_sScriptParam[0] := IntToStr(nItemIdx);
            m_sScriptParam[1] := IntToStr(nPackIdx);
            m_sScriptParam[2] := StdItem.Name;
            GetStdItemByMakeIndex(nPackIdx, StdItem3);
            if StdItem3 <> nil then m_sScriptParam[3] := StdItem3.Name;
            m_nEatItemMakeIndex := UserItem34.MakeIndex;
            sItemName := StdItem.Name;
            nCheckCode := 3;

            //自动叠加的物品
            if CheckSPCode(StdItem.Reserved, RE_ALLOWPILE) and (nPackIdx > 0) then begin
              if PileItems(UserItem, nPackIdx, StdItem) then begin
                m_nEatItemMakeIndex := 0;
                boEatOK := False;
                SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                goto EAT_END;
              end;
            end;

{$IF USESDK = DEBUG}
            SysMsg(Format('nItemIdx: %d; sItemName: %s;nPackIdx: %d', [nItemIdx, sItemName, nPackIdx]), c_Red, t_Hint);
{$IFEND}
            //检查是否为本地图禁止使用的物品
            if m_PEnvir.ForbidItem(sItemName) then begin
              SysMsg('本地图禁止使用 ' + StdItem.FilterName, c_Red, t_Hint);
              goto EAT_END;
            end;

            nCheckCode := 4;
            //灵符类物品控制
            if (StdItem.StdMode = 3) and (StdItem.Shape in [27, 29, 202, 203, 206, 207]) then begin
              if m_PEnvir.m_MapFlag.boCanUseSuperItem and m_PEnvir.AllowSoulItem(sItemName) then begin
                nCheckCode := 5;
                if (nPackIdx > 0) then Monster := TBaseObject(nPackIdx);
                nCheckCode := 6;
                if (nPackIdx > 0) and CretInNear10XY(TBaseObject(nPackIdx), m_nCurrX, m_nCurrY) and (Monster <> nil) and (not Monster.m_boDeath) and (not Monster.m_boGhost) and (Monster.m_btRaceServer >= RC_ANIMAL) then
{$IF USESDK = DEBUG}
                  //SysMsg('灵符攻击目标有效', c_Red, t_Hint)
                  OutputDebugString('灵符攻击目标有效')
{$IFEND}
                else
                  goto EAT_END;
              end else begin
{$IF USESDK = DEBUG}
                SysMsg('本地图不允许使用此道具。', c_Red, t_Hint);
{$IFEND}
                goto EAT_END;
              end;
            end;
            nCheckCode := 190;
            case StdItem.StdMode of
              0..2: begin                                                                           //药,肉(食物)
                  if EatItems(StdItem) then begin
                    if (StdItem.StdMode = 0) and (StdItem.Shape in [200..202, 206, 207, 219]) then begin
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        if UserItem.Dura > 0 then Dec(UserItem.Dura);
                        if (UserItem.Dura <= 0) then begin
                          m_nEatItemMakeIndex := 0;
                          DelBagItem(UserItem34.MakeIndex, '');
                          boEatOK := True;
                        end else begin
                          boEatOK := False;
                          //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                          SendUpdateItem(UserItem);
                        end;
                      end;
                    end else if (StdItem.StdMode = 0) and (StdItem.Shape = 211) then begin          //海神生命神水
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        //n14 := _MIN(High(byte), LoWord(StdItem.AC)) * _Max(1, HiWord(StdItem.AC));
                        n14 := _MIN(m_WAbil.dwMaxHP - m_WAbil.dwHP, UserItem.Dura);
                        if n14 > 0 then begin
                          IncHealthSpell(n14, 0);
                          Dec(UserItem.Dura, n14);
                        end;
                        if (UserItem.Dura <= 0) then begin
                          m_nEatItemMakeIndex := 0;
                          DelBagItem(UserItem34.MakeIndex, '');
                          boEatOK := True;
                        end else begin
                          boEatOK := False;
                          //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                          SendUpdateItem(UserItem);
                        end;
                      end;
                    end else if (StdItem.StdMode = 0) and (StdItem.Shape = 212) then begin          //海神魔法神水
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        n14 := _MIN(m_WAbil.dwMaxMP - m_WAbil.dwMP, UserItem.Dura);
                        if n14 > 0 then begin
                          IncHealthSpell(0, n14);
                          Dec(UserItem.Dura, n14);
                        end;
                        if (UserItem.Dura <= 0) then begin
                          m_nEatItemMakeIndex := 0;
                          DelBagItem(UserItem34.MakeIndex, '');
                          boEatOK := True;
                        end else begin
                          boEatOK := False;
                          //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                          SendUpdateItem(UserItem);
                        end;
                      end;
                    end else begin
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) and (StdItem.Shape <> 5) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        boEatOK := True;
                      end;
                    end;
                  end;
                  goto EAT_END;
                end;
              3: begin
                  case StdItem.Shape of
                    27, 29: begin                                                                   //镇魔符、镇魔神符
                        if (not m_PEnvir.m_MapFlag.boCanReCallEvil) or
                          (Monster.m_btRaceServer <> RC_EVIL) or (Monster.m_Master <> nil) or (not IsProperTarget(Monster)) then begin
{$IF USESDK = DEBUG}
                          SysMsg(FilterItemShowName(StdItem.Name) + '攻击目标无效!', c_Red, t_Hint);
{$IFEND}
                          goto EAT_END;
                        end;
                        for j := 0 to m_SlaveList.Count - 1 do begin
                          if TBaseObject(m_SlaveList[j]).m_btRaceServer = RC_EVIL then begin
                            Inc(n14);
                            if n14 >= g_Config.nMaxRecallEvilCount then Break;
                          end;
                        end;
                        if n14 >= g_Config.nMaxRecallEvilCount then begin
                          SysMsg('你已无法召唤更多的心魔', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        TurnTo(GetNextDirection(m_nCurrX, m_nCurrY, Monster.m_nCurrX, Monster.m_nCurrY));
                        //显示一个效果
                        SendRefMsg(RM_ASSISTSKILL, $0D, Integer(Monster), m_btDirection, MakeLong(Monster.m_nCurrX, Monster.m_nCurrY), '');
                        if Random(g_Config.nRecallEvilRate) = 0 then begin
                          //镇魔符召怪
                          ExecuteScript(g_FunctionNPC, '@镇魔符召怪');
                          Monster.m_Master := Self;
                          Monster.m_btRaceImg := 254;
                          Monster.m_dwMasterRoyaltyTick := GetTickCount + 20 * 60 * 60 * 1000;
                          Monster.m_boSuperMan := g_Config.boEvilSlaveSuperMan;
                          Monster.RecalcAbilitys;
                          m_SlaveList.Add(Monster);
                          Monster.SetTargetCreat(m_TargetCret);
                          Monster.m_wStatusTimeArr[POISON_DONTMOVE] := 1;
                          Monster.HealthSpellChanged;
                          Monster.RefShowName;
                          Monster.SendRefMsg(RM_510, 1, 0, 72, 0, '');
                          //显示心魔控制面板
                          m_nEvilFollowerPower := _MIN(m_nEvilFollowerPowerMax, m_nEvilFollowerPower + StdItem.AC * 1000);
                          ClientQueryEvilFollower;
                          ClearEvilFollower(4);
                          m_dwClearObjTick := GetTickCount();
                          SendDefMessage(CM_RECALLEVIL, Integer(Self), 3, LoWord(m_nEvilFollowerPower), HiWord(m_nEvilFollowerPower), '');
                        end else begin
                          //镇魔符冻结心魔
                          Monster.MakePosion(POISON_DONTMOVE, Round(StdItem.AC / 10) * g_Config.nAntiEvilDontMoveTime, 0);
                        end;
                        {减少持久}
                        if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                          if UserItem.Dura > 0 then Dec(UserItem.Dura);
                          if (UserItem.Dura <= 0) then begin
                            m_nEatItemMakeIndex := 0;
                            DelBagItem(UserItem34.MakeIndex, '');
                            boEatOK := True;
                          end else begin
                            boEatOK := False;
                            //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                            SendUpdateItem(UserItem);
                          end;
                        end;
                      end;
                    202, 203: begin                                                                 //灵符
                        if (not IsProperTarget(Monster)) or (Monster.m_Master <> nil) or (Monster.m_boHideMode) or (CheckSPCode(Monster.m_dwRuleCtrlCode, SP_MON_DISABLELINGFU)) then begin
{$IF USESDK = DEBUG}
                          SysMsg('灵符攻击目标无效', c_Red, t_Hint);
{$IFEND}
                          boEatOK := False;
                          //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                          goto EAT_END;
                        end else begin
                          TurnTo(GetNextDirection(m_nCurrX, m_nCurrY, Monster.m_nCurrX, Monster.m_nCurrY));
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if StdItem.Shape = 203 then begin                                       //灵符(捆)
                              //快速救公主地图
                              if m_PEnvir.m_MapFlag.boFastUseItem then begin
                                n14 := 0;
                                SetLength(TargeList, 0);
                                ObjList := TList.Create;
                                try
                                  m_PEnvir.GetRangeBaseObject(Monster.m_nCurrX, Monster.m_nCurrY, 20, True, ObjList);
                                  for j := 0 to ObjList.Count - 1 do begin
                                    BaseObject := TBaseObject(ObjList.Items[j]);
                                    if (BaseObject = Monster) or (BaseObject.m_btRaceServer = RC_PRINCESSGUARD) or
                                      (BaseObject.m_Master <> nil) or (BaseObject.m_boHideMode) or
                                      CheckSPCode(BaseObject.m_dwRuleCtrlCode, SP_MON_DISABLELINGFU) or
                                      BaseObject.m_boDeath or BaseObject.m_boGhost or BaseObject.m_boHideMode then Continue;

                                    if IsProperTarget(BaseObject) then begin
                                      BaseObject.m_boHideMode := True;
                                      BaseObject.SendDelayMsg(Self, RM_LINGFUSTRUCK, 0, g_Config.nLinfuDecHP, 0, 0, '', 300);
                                      Inc(n14);
                                      SetLength(TargeList, n14);
                                      TargeList[n14 - 1] := Integer(BaseObject);
                                    end;
                                    if n14 >= UserItem.Dura then Break;
                                  end;
                                finally
                                  ObjList.free;
                                end;
                                //扣除灵符持久
                                if n14 >= UserItem.Dura then UserItem.Dura := 0;
                              end else
                                n14 := 1;
                              //发送效果
                              if n14 > 1 then begin
                                sTmp := EnCodeBuffer(@TargeList[0], SizeOf(Integer) * n14);
                                SendRefMsg(RM_USEBINDLINGFU, n14, Integer(Monster), $0D, m_btDirection, sTmp);
                              end else begin
                                SendRefMsg(RM_ASSISTSKILL, $0D, Integer(Monster), m_btDirection, MakeLong(Monster.m_nCurrX, Monster.m_nCurrY), '');
                              end;
                              //目标怪物
                              Monster.m_boHideMode := True;
                              Monster.SendDelayMsg(Self, RM_LINGFUSTRUCK, 0, g_Config.nLinfuDecHP, 0, 0, '', 300);

                              //扣除灵符
                              if (UserItem.Dura > 0) then Dec(UserItem.Dura, n14);
                              if (UserItem.Dura <= 0) then begin
                                m_nEatItemMakeIndex := 0;
                                DelBagItem(UserItem34.MakeIndex, '');
                                boEatOK := True;
                              end else begin
                                boEatOK := False;
                                //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                                SendUpdateItem(UserItem);
                              end;
                            end else begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                              n14 := 1;
                            end;
                            //触发脚本
                            m_sScriptParam[5] := IntToStr(n14);                                     //杀怪数量
                            ExecuteScript(g_FunctionNPC, '@灵符杀怪');
                          end;
                        end;
                      end;
                    206, 207: begin
                        if (not CheckSPCode(Monster.m_dwRuleCtrlCode, SP_MON_ALLOWCATCH)) then begin
                          SysMsg('灵兽项圈不能用来捕捉此怪物!', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        if (Monster.m_Master <> nil) or (Monster.m_boIsPet) then begin
                          SysMsg('灵兽已有主人,不能被捕捉', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        {灵兽减血}
                        Monster.SendDelayMsg(Self, RM_LINGFUSTRUCK, 0, g_Config.nChapLetDecHP, 0, 0, '', 300);
                        n14 := Monster.m_WAbil.dwHP div g_Config.nChapLetMonHPRate;
                        if n14 <= 2 then n14 := 2;
                        if (Random(20) > (Monster.m_wSlaveExpLevel + g_Config.nChapLetMonLevel {10})) and ((Random(n14) = 0)) then begin
                          nCode := $123F;
                          m_sScriptParam[0] := Monster.m_sCharName;                                 //灵兽名称
                          m_sScriptParam[1] := IntToStr(Monster.m_wAppr);                           //灵兽Appr
                          m_sScriptParam[2] := IntToStr(Monster.m_wSlaveExpLevel);                  //灵兽等级
                          m_sScriptParam[3] := IntToStr(nItemIdx);
                          ExecuteScript(g_FunctionNPC, '@捕捉灵兽');
                        end else begin
                          nCode := $123E;
                        end;
                        //显示一个效果
                        TurnTo(GetNextDirection(m_nCurrX, m_nCurrY, Monster.m_nCurrX, Monster.m_nCurrY));
                        SendRefMsg(RM_ASSISTSKILL, nCode, Integer(Monster), m_btDirection, MakeLong(Monster.m_nCurrX, Monster.m_nCurrY), '');
                        if nCode = $123F then Monster.MakeGhost;                                    //抓捕成功
                        if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                          if StdItem.Shape = 207 then begin                                         //捆
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              boEatOK := False;
                              //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end else begin
                            m_nEatItemMakeIndex := 0;
                            DelBagItem(UserItem34.MakeIndex, '');
                            boEatOK := True;
                          end;
                        end;
                      end;
                    210: begin
                        tm := MakeLong(MakeWord(UserItem.btValue[4], UserItem.btValue[5]),
                          MakeWord(UserItem.btValue[6], UserItem.btValue[7]));
                        if (tm = 0) then begin                                                      //第一次使用
                          tm := DateTimeToWolTIme(Now);
                          tm := tm + (StdItem.sC * 86400);
                          Move(tm, UserItem.btValue[4], 4);                                         //激活时间
                          UserItem.btItemExt[4] := 1;                                               //绑定
                          SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                          SendUpdateItem(UserItem);
                        end else begin
                          if (DateTimeToWolTIme(Now) > tm) then begin
                            SysMsg('该物品已经到期', c_Red, t_Hint);
                          end else begin
                            ExecuteScript(g_ManageNPC, '@_释放_兽尊灵丹');
                          end;
                        end;
                      end
                  else begin
                      if (StdItem.Shape = 201) and (StdItem.AniCount = 20000) then begin
                        if m_PEnvir.m_MapFlag.boNORANDOMMOVE then begin
                          SysMsg('此地图禁止使用随机', c_Red, t_Hint);
                          goto EAT_END;
                        end else begin
                          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
                          BaseObjectMove(m_sMapName, '', '');
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura = 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;

                      end else if (StdItem.Shape = 15) or ((StdItem.Shape = 17) and ((StdItem.Looks = 729) or (StdItem.Looks = 942))) then begin
                        //回城神石
                        if (m_wShopItemCount > 0) or m_boArrow then goto EAT_END;                   //禁止使用回城石的条件

                        if (GetTickCount - m_dwUseStoreTick) < 10000 then begin
                          SysMsg('每隔10秒才允许使用回城石一次。', c_Red, t_Hint);
                          goto EAT_END;
                        end;

                        if m_PEnvir.m_MapFlag.boNOSTOREMOVE then begin
                          SysMsg('当前地图禁止使用回城石。', c_Red, t_Hint);
                          goto EAT_END;
                        end;

                        if StdItem.AniCount = 0 then begin
                          nX := MakeWord(UserItem.btValue[0], UserItem.btValue[1]);
                          nY := MakeWord(UserItem.btValue[2], UserItem.btValue[3]);
                          sMAP := '';
                          for j := 4 to 9 do begin
                            if UserItem.btValue[j] = 0 then Break;
                            sMAP := sMAP + Chr(UserItem.btValue[j]);
                          end;

                          if (sMAP <> '') then begin
                            m_sScriptParam[0] := m_PEnvir.m_sMapName;
                            m_sScriptParam[1] := sMAP;
                            SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
                            SpaceMove(sMAP, nX + Random(8) - 4, nY + Random(8) - 4, 0, nil);
                            m_dwUseStoreTick := GetTickCount;
                            ExecuteScript(g_FunctionNPC, '@使用回城石');
                            if (StdItem.Shape = 17) then begin
                              if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                                if UserItem.Dura > 0 then Dec(UserItem.Dura);
                                if (UserItem.Dura = 0) then begin
                                  m_nEatItemMakeIndex := 0;
                                  DelBagItem(UserItem34.MakeIndex, '');
                                  boEatOK := True;
                                end else begin
                                  boEatOK := False;
                                  SendUpdateItem(UserItem);
                                end;
                              end;
                            end;
                          end else
                            SysMsg('该' + StdItem.Name + '没有刻地名,请到各地老兵处记录回城点。', c_Red, t_Hint);
                        end else begin
                          ExecuteScript(g_FunctionNPC, '@使用回城石');
                          boEatOK := False;
                          SendUpdateItem(UserItem);
                        end;
                      end else begin                                                                //其他类物品
                        if EatItems(StdItem) then begin
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              boEatOK := False;
                              //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    end;
                  end;
                  goto EAT_END;
                end;
              4, 8: begin                                                                           //书
                  nCheckCode := 192;
                  if (g_FunctionNPC <> nil) and (StdItem.AniCount > 0) then begin
                    SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                    UseStdmodeFunItem(StdItem, True);
                  end else begin
                    boEatOK := ReadBook(StdItem);
                    if boEatOK then begin
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                      end;
                      //刺杀剑法
                      if (m_MagicSkills[12] <> nil) and (not m_boUseThrusting) then begin
                        ThrustingOnOff(True);
                        SendSocket(nil, '+LNG');
                      end;
                      //半月弯刀
                      if (m_MagicSkills[25] <> nil) and (not m_boUseHalfMoon) then begin
                        HalfMoonOnOff(True);
                        SendSocket(nil, '+WID');
                      end;
                    end;
                  end;
                end;
              12: begin                                                                             //盾牌升级
                  SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                  ExecuteScript(g_FunctionNPC, '@TigerShield');
                end;
              30: begin                                                                             //精英勋章
                  nCheckCode := 193;
                  if (StdItem.Looks = 8020) then begin
                    SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                    ExecuteScript(g_FunctionNPC, '@EliteMedal');
                  end;
                end;
              31: begin                                                                             //解包物品
                  nCheckCode := 194;
                  if StdItem.AniCount = 0 then begin                                                //打包的物品
                    if (m_ItemList.Count + 6 - 1) <= m_nBagSize then begin
                      if m_boPneuma then SendDelItems(UserItem);
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                      end;
                      GetUnBindItems(GetUnbindItemName(StdItem.Shape), 6);
                      boEatOK := True;
                    end;
                  end else if StdItem.AniCount = 255 then begin                                     //魔法字体、魔法颜料
                    if StdItem.AC > 1 then begin
                      m_btChatColor := StdItem.AC;
                      SysMsg('您改变了文字颜色', c_Red, t_Hint);
                    end;
                    if StdItem.MAC > 0 then begin
                      m_btChatFont := StdItem.MAC;
                      SysMsg('您改变了文字字体', c_Red, t_Hint);
                    end;
                    if (StdItem.DC > 0) and (StdItem.DC <= 77) then begin
                      if (m_MagicSkills[StdItem.DC] <> nil) then begin
                        m_MagicSkills[StdItem.DC].nSkillColor :=
                          MakeLong(MakeWord(HiWord(StdItem.MC),
                          LoWord(StdItem.MC)), MakeWord(HiWord(StdItem.SC),
                          LoWord(StdItem.SC)));
                        SendDefMessage($B4A4, m_MagicSkills[StdItem.DC].nSkillColor, StdItem.DC, 0, 0, '');
                        SysMsg('您改变了魔法颜色', c_Red, t_Hint);
                      end;
                    end;
                    if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                      if UserItem.Dura > 0 then Dec(UserItem.Dura);
                      if (UserItem.Dura <= 0) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        boEatOK := True;
                      end else begin
                        //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                        SendUpdateItem(UserItem);
                      end;
                    end;
                  end else if StdItem.AniCount = 254 then begin                                     //天气卷轴
                    if GetTickCount - m_PEnvir.m_dwChangeTick < 2 * 60 * 1000 then begin
                      SysMsg('天气效果2分钟内不可以连续更换!', c_Red, t_Hint);
                      goto EAT_END;
                    end;
                    m_PEnvir.m_dwChangeTick := GetTickCount();
                    m_PEnvir.m_MapFlag.nWeather := MakeWord(LoWord(StdItem.AC), HiWord(StdItem.AC));
                    m_PEnvir.m_MapFlag.wWindSpeed := MakeWord(LoWord(StdItem.MAC), HiWord(StdItem.MAC));
                    m_PEnvir.m_MapFlag.dwWindColor := MakeLong(MakeWord(LoWord(StdItem.DC), HiWord(StdItem.DC)), MakeWord(LoWord(StdItem.MC), HiWord(StdItem.MC)));
                    UserEngine.SendMapMsg(m_PEnvir, Self, RM_DAYCHANGING, 0, 0, 0, 0, '');
                    UserEngine.SendMapMsg(m_PEnvir, Self, RM_TITLEMSM, 0, $38FF, $FC, 10, m_sCharName + '改变' + m_PEnvir.m_sMapDesc + '的天气为' + StdItem.Name + ',您现在可以打开天气效果欣赏。');
                    if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                      if UserItem.Dura > 0 then Dec(UserItem.Dura);
                      if (UserItem.Dura <= 0) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        boEatOK := True;
                      end else begin
                        //SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                        SendUpdateItem(UserItem);
                      end;
                    end;
                  end else begin                                                                    //其他物品,比如卷、回城石
                    if (m_wShopItemCount > 0) or m_boArrow then goto EAT_END;
                    if UseStdmodeFunItem(StdItem) then begin
                      if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        boEatOK := True;
                      end;
                    end;
                  end;
                end;
              32: begin
                  nCheckCode := 195;                                                                //空马牌
                  if (m_btHorseType = 0) or (HorseName = '') then begin
                    SysMsg('你现在没有马,无法使用马牌(空)', c_Red, t_Hint);
                    goto EAT_END;
                  end;
                  UserItem2 := nil;
                  if m_UseItems[U_RIGHTHAND].wIndex > 0 then begin
                    UserItem2 := @m_UseItems[U_RIGHTHAND];
                    StdItem2 := UserEngine.GetStdItem(UserItem2.wIndex);
                    if (StdItem2.StdMode <> 33) then UserItem2 := nil;
                  end;
                  //杂物位置
                  if (UserItem2 = nil) and (m_UseItems[U_CHARM].wIndex > 0) then begin
                    UserItem2 := @m_UseItems[U_CHARM];
                    StdItem2 := UserEngine.GetStdItem(UserItem2.wIndex);
                    if (StdItem2.StdMode <> 33) then UserItem2 := nil;
                  end;
                  if UserItem2 <> nil then begin
                    SysMsg('你已绑定好了马牌,不用在次绑定马牌', c_Red, t_Hint);
                    goto EAT_END;
                  end;

                  //给他一个马牌
                  New(UserItem2);
                  if UserEngine.CopyToUserItemFromName('马牌', UserItem2) then begin
                    StdItem2 := UserEngine.GetStdItem(UserItem2.wIndex);
                    m_ItemList.Add(UserItem2);
                    UserItem2.Dura := UserItem2.DuraMax;
                    if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                      m_nEatItemMakeIndex := 0;
                      DelBagItem(UserItem34.MakeIndex, '');
                      WeightChanged();
                      SendDefMessage(SM_EAT_OK, 0, 0, 0, 0, '');
                    end;
                    SendAddItem(UserItem2);
                    //绑定马牌
                    UserItem2.btValue[0] := m_btHorseType;
                    for j := 1 to Length(HorseName) do
                      UserItem2.btValue[j] := byte(HorseName[j]);
                    SendUpdateItem(UserItem2);
                    m_btHorseType := 0;
                    if ClientTakeOnItems(U_RIGHTHAND, UserItem2.MakeIndex, StdItem2.Name, True) then
                      SysMsg(Format('你的%s马牌已经装备到身上', [HorseName]), c_Red, t_Hint);
                    boEatOK := True;
                    //Exit;
                  end else
                    Dispose(UserItem2);
                end;
              36, 46: begin                                                                         //天气卷轴
                  nCheckCode := 196;
                  if (StdItem.StdMode = 36) and (StdItem.Shape = 1) then begin
                    m_PEnvir.m_MapFlag.nWeather := MakeWord(LoWord(StdItem.AC), HiWord(StdItem.AC));
                    m_PEnvir.m_MapFlag.wWindSpeed := MakeWord(LoWord(StdItem.MAC), HiWord(StdItem.MAC));
                    m_PEnvir.m_MapFlag.dwWindColor := MakeLong(MakeWord(LoWord(StdItem.DC), HiWord(StdItem.DC)), MakeWord(LoWord(StdItem.MC), HiWord(StdItem.MC)));
                    UserEngine.SendMapMsg(m_PEnvir, Self, RM_DAYCHANGING, 0, 0, 0, 0, '');
                    UserEngine.SendBroadCastMsgExt(m_sCharName + '改变' + m_PEnvir.m_sMapDesc + '的天气为' + ReplaceStr(StdItem.Name, '卷轴', '') + ',您现在可以打开天气效果欣赏。', t_center);
                    if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                      if UserItem.Dura > 0 then Dec(UserItem.Dura);
                      if (UserItem.Dura <= 0) then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        boEatOK := True;
                      end else begin
                        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                        SendUpdateItem(UserItem);
                      end;
                    end
                  end else if (StdItem.StdMode = 46) and (StdItem.Shape = 106) then begin           //财神许愿符
                    if m_PEnvir.m_MapFlag.boCanUseSuperItem and m_PEnvir.AllowSoulItem(sItemName) then begin
                      if (abs(45 - m_nCurrX) > 3) or (abs(45 - m_nCurrY) > 3) then begin
                        SysMsg('您站的太远了,请在许愿池附近使用该物品', c_Red, t_Hint);
                        goto EAT_END;
                      end else begin
                        SendRefMsg(RM_ASSISTSKILL, $1536, 0, 4, MakeLong(45, 45), '');
                        SendWishAwardInfo();
                        if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                          if UserItem.Dura > 0 then Dec(UserItem.Dura);
                          if (UserItem.Dura <= 0) then begin
                            m_nEatItemMakeIndex := 0;
                            DelBagItem(UserItem34.MakeIndex, '');
                            boEatOK := True;
                          end else begin
                            boEatOK := False;
                            SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                            SendUpdateItem(UserItem);
                          end;
                        end;
                      end;
                    end else
                      goto EAT_END;
                  end else begin                                                                    //执行脚本
                    if (StdItem.AniCount > 0) then begin
                      SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                      UseStdmodeFunItem(StdItem, True);
                    end;
                    goto EAT_END;
                  end;
                end;
              37: begin
                  nCheckCode := 197;
                  case StdItem.Shape of
                    2: begin
                        if (m_wShopItemCount > 0) or m_boArrow then goto EAT_END;                   //随机神石
                        if m_PEnvir.m_MapFlag.boNORANDOMMOVE then begin
                          SysMsg('此地图禁止使用随机', c_Red, t_Hint);
                          goto EAT_END;
                        end else begin
                          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
                          BaseObjectMove(m_sMapName, '', '');
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura = 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    3: begin
                        if m_sDearName = '' then begin
                          SysMsg('尚未婚配,不可以种植' + g_Config.sLoveTree, c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        if not InPlantZone then begin
                          SysMsg('该地区不可以植树。', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        GetFrontPosition(nX, nY);
                        sTmp := m_sCharName;
                        if (m_sDearName <> '') then sTmp := sTmp + '和' + m_sDearName;
                        sTmp := sTmp + '的' + g_Config.sLoveTree;
                        Monster := UserEngine.RegenMonsterByName(m_PEnvir, nX, nY, g_Config.sLoveTree, sTmp, 3);
                        if Monster <> nil then begin
                          Monster.m_wSlaveMakeLevel := 0;
                          Monster.m_wSlaveExpLevel := 0;
                          Monster.RecalcAbilitys;
                          Monster.RefNameColor;
                          SysMsg('恭喜您,爱情之树种植成功,您的爱情之树现在的寿命是3天。', c_Red, t_Hint);
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    4: begin
                        if m_sDearName = '' then begin
                          SysMsg('尚未婚配,不可以种植' + g_Config.sLoveTree, c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        if not InPlantZone then begin
                          SysMsg('该地区不可以植树。', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        sTmp := m_sCharName;
                        if m_sDearName <> '' then sTmp := sTmp + '和' + m_sDearName;
                        sTmp := sTmp + '的' + g_Config.sLoveTree;

                        ObjList := TList.Create;
                        try
                          m_PEnvir.GetRangeBaseObject(m_nCurrX, m_nCurrY, 2, True, ObjList);
                          boFind := False;
                          for j := 0 to ObjList.Count - 1 do begin
                            Monster := TBaseObject(ObjList[j]);
                            if (Monster.m_wAppr = 241) and (CompareText(Monster.m_sCharName, sTmp) = 0) then begin
                              Monster.m_nLifeSpan := Monster.m_nLifeSpan + StdItem.AC;
                              SysMsg(sTmp + '寿命成功延长' + IntToStr(StdItem.AC) + '天,死亡时间推迟到' + DateToChStr(Monster.m_dtBirthday + Monster.m_nLifeSpan, True), c_Red, t_Hint);
                              if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                                if UserItem.Dura > 0 then Dec(UserItem.Dura);
                                if (UserItem.Dura <= 0) then begin
                                  m_nEatItemMakeIndex := 0;
                                  DelBagItem(UserItem34.MakeIndex, '');
                                  boEatOK := True;
                                end else begin
                                  SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                                  SendUpdateItem(UserItem);
                                end;
                              end;
                              boFind := True;
                              Break;
                            end;
                          end;
                        finally
                          ObjList.free;
                        end;
                        if not boFind then
                          SysMsg('附近没有发现' + sTmp + ',请在5格范围内使用', c_Red, t_Hint);
                      end;
                    202: begin
                        if PackageItems(nPackIdx) then begin
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    10: begin
                        if (m_Pet = nil) or (m_PetInfo[0].nMakeIndex = 0) then begin
                          SysMsg('你的身边没有可喂食的宠物,不能喂食。', c_Red, t_Hint);
                          goto EAT_END;
                        end;

                        if PetStoreAddExp(m_PetInfo[0].nMakeIndex, StdItem.AC, LoWord(StdItem.AC), True) then begin
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              SendDelItems(UserItem);
                              DelBagItem(UserItem34.MakeIndex, '');
                              goto EAT_END;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    11: begin
                        m_boRideOn := False;
                        if StdItem.AniCount <> m_btGender then begin
                          SysMsg('性别不符,不能使用', c_Red, t_Hint);
                          m_boRideOn := True;
                          goto EAT_END;
                        end;

                        if m_UseItems[U_RIDEDRESS].wIndex > 0 then begin
                          m_UseItems[U_RIDEDRESS].wIndex := 0;
                          m_nDressShape := 0;
                          SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
                        end;

                        if ((m_nDressShape and $000000C8) = $000000C8) then begin
                          if m_UseItems[0].wIndex = 0 then
                            m_nDressShape := 0
                          else begin
                            StdItem2 := UserEngine.GetStdItem(m_UseItems[0].wIndex);
                            if StdItem2 = nil then
                              m_nDressShape := 0
                            else
                              m_nDressShape := MakeLong(MakeWord(StdItem2.Shape, $00), HiWord(m_nDressShape));
                          end;
                          if m_boRideOn then ClientRideOff();
                        end else begin
                          m_nDressShape := MakeLong($00C8, HiWord(m_nDressShape));
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                        RecalcAbilitys();
                        SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                        SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
                        m_nMagicStatus := GetMagicStatus;
                        Status2Changed;
                        FeatureChanged;
                      end;
                    14, 30: begin
                        //极品御兽天衣、仙魂御龙袍
                        m_boRideOn := False;
                        if StdItem.AniCount <> m_btGender then begin
                          SysMsg('性别不符,不能使用', c_Red, t_Hint);
                          m_boRideOn := True;
                          goto EAT_END;
                        end;

                        if m_UseItems[U_RIDEDRESS].wIndex > 0 then begin
                          m_UseItems[U_RIDEDRESS].wIndex := 0;
                          m_nDressShape := 0;
                          SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
                          if m_boRideOn then ClientRideOff();
                        end else begin
                          m_UseItems[U_RIDEDRESS] := UserItem^;
                          SendUseitems();
                        end;

                        RecalcAbilitys();
                        SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                        SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
                        m_nMagicStatus := GetMagicStatus;
                        Status2Changed;
                        FeatureChanged;
                      end;
                    200: begin
                        if SuperRepairUseItems then begin
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                    207, 209: begin
                        if ExecuteScript(g_ManageNPC, '@加点装备') then begin
                          if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                            if UserItem.Dura > 0 then Dec(UserItem.Dura);
                            if (UserItem.Dura <= 0) then begin
                              m_nEatItemMakeIndex := 0;
                              DelBagItem(UserItem34.MakeIndex, '');
                              boEatOK := True;
                            end else begin
                              SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                              SendUpdateItem(UserItem);
                            end;
                          end;
                        end;
                      end;
                  else begin
                      SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                      if UseStdmodeFunItem(StdItem) then begin
                        if (m_nEatItemMakeIndex = UserItem34.MakeIndex) then begin
                          if (UserItem.Dura > 0) and (StdItem.Source <> 1) then Dec(UserItem.Dura);
                          if (UserItem.Dura = 0) and (StdItem.Source <> 1) then begin
                            m_nEatItemMakeIndex := 0;
                            SendDelItems(UserItem);
                            DelBagItem(UserItem34.MakeIndex, '');
                            boEatOK := True;
                          end else begin
                            SendUpdateItem(UserItem);
                          end;
                        end;
                      end;
                    end;
                  end;
                end;
              49: begin
                  nCheckCode := 198;
                  m_nEatItemMakeIndex := 0;
                  case StdItem.Shape of
                    51: begin                                                                       //豹魔石
                        if (m_Pet = nil) and (m_PetInfo[0].nMakeIndex = 0) and (not IsDownPetItem(UserItem.MakeIndex)) then begin //放出豹子
                          //检查豹子状态
                          tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
                          if (tm > 0) and (tm + (PETMAXUSEDAY * 86400) <= DateTimeToWolTIme(Now)) then begin //第5天死亡
                            SysMsg('你的宠物已经死亡。', c_Red, t_Hint);
                            goto EAT_END;
                          end;

                          //绑定灵兽
                          if (not g_Config.boClassicServer) and (UserItem.btItemExt[4] = 0) then begin
                            UserItem.btItemExt[4] := 1;
                            SendUpdateItem(UserItem);
                          end;

                          if tm = 0 then begin
                            tm := DateTimeToWolTIme(Now);
                            UserItem.btValue[0] := LoByte(LoWord(tm));
                            UserItem.btValue[1] := HiByte(LoWord(tm));
                            UserItem.btValue[2] := LoByte(HiWord(tm));
                            UserItem.btValue[3] := HiByte(HiWord(tm));
                            SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                            m_sPetName := '';
                            SendUpdateItem(UserItem);
                          end;
                          PetShow(UserItem.MakeIndex);

                          sMAP := _PETNAME[_MIN(15, StdItem.AniCount)][_MIN(3, UserItem.btValue[9])];
                          if m_Pet <> nil then begin
                            n14 := DateTimeToWolTIme(Now) - tm;
                            n14 := n14 div 86400;
                            if n14 <= 2 then
                              SysMsg('您的' + sMAP + '精神饱满。', c_Red, t_Hint)
                            else if n14 = 3 then
                              SysMsg('您的' + sMAP + '状态为微饿。红袖处有兽粮出售。', c_Red, t_Hint)
                            else if n14 = 4 then
                              SysMsg('您的' + sMAP + '状态为饥饿。红袖处有兽粮出售。', c_Red, t_Hint)
                            else
                              SysMsg('您的' + sMAP + '已饿死,您可以带着神水请驯兽师帮您复活。商城内有神水出售。', c_Red, t_Hint);
                            nCheckCode := 19891;
                            m_Pet.RefShowName;
                            ExecuteScript(g_FunctionNPC, '@ReleasePet');
                            if UserItem.btValue[9] < 3 then
                              SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 3, UserItem.MakeIndex, 0, '', 200) //刷新灵兽排名
                            else
                              SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 4, UserItem.MakeIndex, 0, '', 200);
                          end;
                        end else begin                                                              //收起豹子
                          if (m_Pet <> nil) and
                            (m_PetInfo[0].nMakeIndex <> UserItem.MakeIndex) and
                            (not IsDownPetItem(UserItem.MakeIndex)) then
                          begin
                            SysMsg('你无法同时使两个灵兽跟随', c_Red, t_Hint);
                            goto EAT_END;
                          end;

                          if (m_PackPet <> nil) and (m_PetInfo[1].nMakeIndex = UserItem.MakeIndex) then
                            SysMsg('你的宠物正在替你守摊,停止守摊后才能召唤你的宠物。', c_Red, t_Hint)
                          else if (m_PetInfo[4].nMakeIndex = UserItem.MakeIndex) then
                            SysMsg('你的宠物正在替你探宝,停止探宝后才能召唤你的宠物。', c_Red, t_Hint)
                          else if (m_PetInfo[5].nMakeIndex = UserItem.MakeIndex) then
                            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '该灵兽处于魂佑附体状态,无法跟随')
                          else
                            PetHide(UserItem.MakeIndex);
                        end;
                      end;
                    52: begin                                                                       //兽粮
                        if (m_Pet = nil) or (m_PetInfo[0].nMakeIndex = 0) then begin
                          SysMsg('你的身边没有可喂食的宠物,不能喂食。', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        if PetStoreAddExp(m_PetInfo[0].nMakeIndex, StdItem.DuraMax, LoWord(StdItem.AC), True) then begin
                          m_nEatItemMakeIndex := 0;
                          SendDelItems(UserItem);
                          DelBagItem(UserItem34.MakeIndex, '');
                          boEatOK := True;
                          goto EAT_END;
                        end;
                      end;
                    15, 16, 17, 18: begin
                        //摊位样式,摊位旗帜,百变披风
                        if (StdItem.Shape = 18) and (m_boRideOn or m_boCatapultMode) then begin
                          SysMsg('你现在不可以使用变身披风', c_Red, t_Hint);
                          goto EAT_END;
                        end;
                        boEatOK := CheckUserItemTimeOut(UserItem, StdItem);
                        if boEatOK then begin
                          DelBagItem(UserItem34.MakeIndex, '');
                          goto EAT_END;
                        end else begin
                          if StdItem.Shape = 15 then begin
                            if StdItem.AC > 1 then begin
                              m_btChatColor := StdItem.AC;
                              SysMsg('您改变了文字颜色', c_Red, t_Hint);
                            end;
                            if StdItem.MAC > 0 then begin
                              m_btChatFont := StdItem.MAC;
                              SysMsg('您改变了文字字体', c_Red, t_Hint);
                            end;
                            if (StdItem.DC > 0) and (StdItem.DC <= 77) then begin
                              if (m_MagicSkills[StdItem.DC] <> nil) then begin
                                m_MagicSkills[StdItem.DC].nSkillColor := MakeLong(MakeWord(HiWord(StdItem.MC),
                                  LoWord(StdItem.MC)),
                                  MakeWord(HiWord(StdItem.SC),
                                  LoWord(StdItem.SC)));
                                SendDefMessage($B4A4, m_MagicSkills[StdItem.DC].nSkillColor, StdItem.DC, 0, 0, '');
                                SysMsg('您改变了魔法颜色', c_Red, t_Hint);
                              end;
                            end;
                          end else if StdItem.Shape = 16 then begin                                 //摊位类型
                            m_wShopKind := StdItem.DC;
                            SysMsg('您改变了摊位类型', c_Red, t_Hint);
                          end else if StdItem.Shape = 17 then begin                                 //摊位旗帜
                            m_btShopBanner := StdItem.DC;
                            m_nBannerColor :=
                              MakeLong(MakeWord(LoWord(StdItem.MC),
                              HiWord(StdItem.MC)), MakeWord(LoWord(StdItem.SC),
                              HiWord(StdItem.SC)));
                            SysMsg('您改变了摊位旗帜', c_Red, t_Hint);
                          end else if StdItem.Shape = 18 then begin                                 //变身披风
                            if (StdItem.DC = m_wBianshenImg) and (StdItem.MC = m_wBianshenAppr) then begin //取消变身
                              m_wBianshenImg := 0;
                              m_wBianshenAppr := 0;
                            end else begin
                              m_wBianshenImg := StdItem.DC;
                              m_wBianshenAppr := StdItem.MC;
                            end;
                            if m_wExtraLevel > 0 then begin
                              if m_wBianshenAppr = 0 then
                                SendMsg(Self, RM_FENGHAO, MakeWord(8, LoByte(m_wExtraLevel)), GetPneumaAmbit, HiByte(m_wExtraLevel), 0, GetExtraLevelName)
                              else
                                SendMsg(Self, RM_FENGHAO, MakeWord(8, 0), 0, 0, 0, '');
                            end;
                            SendRefMsg(RM_FENGHAO, 64, m_wBianshenImg, m_wBianshenAppr, 0, '');
                          end;
                          goto EAT_END;
                        end;
                      end;
                    22: begin
                        //御兽天衣 ,御兽天袍 Anicount=0为男性,Anicount=1为女性
                        boEatOK := CheckUserItemTimeOut(UserItem, StdItem);
                        m_boRideOn := False;
                        if StdItem.AniCount <> m_btGender then begin
                          SysMsg('性别不符,不能使用', c_Red, t_Hint);
                          m_boRideOn := True;
                          goto EAT_END;
                        end;
                        if boEatOK then begin
                          DelBagItem(UserItem34.MakeIndex, '');
                          goto EAT_END;
                        end else begin

                          if m_UseItems[U_RIDEDRESS].wIndex > 0 then begin
                            m_UseItems[U_RIDEDRESS].wIndex := 0;
                            m_nDressShape := 0;
                            SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
                          end;

                          if ((m_nDressShape and $000000C8) = $000000C8) then begin
                            if m_UseItems[0].wIndex = 0 then
                              m_nDressShape := 0
                            else begin
                              StdItem2 := UserEngine.GetStdItem(m_UseItems[0].wIndex);
                              if StdItem2 = nil then
                                m_nDressShape := 0
                              else
                                m_nDressShape := MakeLong(MakeWord(StdItem2.Shape, $00), HiWord(m_nDressShape));
                            end;
                            if m_boRideOn then ClientRideOff();
                          end else begin
                            m_nDressShape := MakeLong($00C8, HiWord(m_nDressShape));
                          end;
                          RecalcAbilitys();
                          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                          SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
                          m_nMagicStatus := GetMagicStatus;
                          Status2Changed;
                          FeatureChanged;
                          goto EAT_END;
                        end;
                      end;
                    55, 56: ;                                                                       //封元印
                    107: begin
                        m_ExpeditionCount := 0;
                        FillChar(m_ExpeditionBox, SizeOf(TExpeditionBox), #0);
                        UseStdmodeFunItem(StdItem);
                        m_nEatItemMakeIndex := 0;
                        boEatOK := True;
                        goto EAT_END;
                      end
                  else begin                                                                        //49类的其他物品,同37类物品,但支持使用天数
                      boEatOK := CheckUserItemTimeOut(UserItem, StdItem);
                      if boEatOK then begin
                        m_nEatItemMakeIndex := 0;
                        DelBagItem(UserItem34.MakeIndex, '');
                        goto EAT_END;
                      end else begin
                        UseStdmodeFunItem(StdItem);
                        goto EAT_END;
                      end;
                    end;
                  end;
                end;
              59: begin
                  nCheckCode := 199;
                  if StdItem.Shape in [10..18] then begin
                    ExecuteScript(g_FunctionNPC, '@圣灵宝石' + IntToStr(StdItem.Shape));
                    SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                  end;
                end;
              82, 83: begin
                  nCheckCode := 200;
                  if StdItem.Shape = 131 then begin
                    ExecuteScript(g_FunctionNPC, '@AppraisalItem' + IntToStr(StdItem.AniCount));
                    SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
                  end;
                end;
            end;
          end;
        end;
      end;
    end else begin
      //SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotUseItemMsg);
      SysMsg(g_sCanotUseItemMsg, c_Pink, t_Hint);
    end;

    EAT_END:
    nCheckCode := 201;
    if boEatOK then begin
      //WeightChanged(); //这里不需要了
      SendDefMessage(SM_EAT_OK, 0, 0, 0, 0, '');
      nCheckCode := 202;
      if StdItem.boGameLog = 1 then
        AddGameDataLog('11' + #9 +
          m_sMapName + #9 +
          IntToStr(m_nCurrX) + #9 +
          IntToStr(m_nCurrY) + #9 +
          m_sCharName + #9 +
          sItemName + #9 +
          IntToStr(UserItem34.MakeIndex) + #9 +
          '1' + #9 +
          '0');
    end else begin
      SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
    end;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode, m_sCharName, nItemIdx, sItemName, nPackIdx]));
      MainOutMessage(E.Message);
    end;
  end;
end;

{客户端快捷交易}

procedure TPlayObject.ClientQueryUserSet(ProcessMsg: pTProcessMessage);
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnClientQueryUserSet(Self, ProcessMsg);
  except
    MainOutMessage(Format('TPlayObject::ClientQueryUserSet SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//发送货物明细

procedure TPlayObject.ClientUserBuyItem(nIdent, nParam1, nInt, nZz: Integer; sMsg: string; nType: Integer = 0); //004DCA10
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnClientUserBuyItem(Self, nIdent, nParam1, nInt, nZz, sMsg);
  except
    MainOutMessage(Format('TPlayObject::ClientUserBuyItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

procedure TPlayObject.ClientUserSellItem(nParam1, nMakeIndex: Integer; sMsg: string);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  Merchant                              : TMerchant;
  sName                                 : string;
begin
  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];
    if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
      {取自定义物品名称}
      sName := '';
      ItemUnit.GetCustomItemName(UserItem, sName);

      if (CompareText(sMsg, sName) = 0) then begin
        Merchant := UserEngine.FindMerchant(TObject(nParam1));
        if (Merchant <> nil) and
          (Merchant.m_boSell) and
          (IsEnvir(Merchant.m_PEnvir) and
          (abs(Merchant.m_nCurrX - m_nCurrX) < 15) and
          (abs(Merchant.m_nCurrY - m_nCurrY) < 15)) then begin
          if Merchant.ClientSellItem(Self, UserItem) then begin
            if UserItem.btValue[13] and $01 = 1 then begin
              ItemUnit.DelCustomItemName(UserItem.MakeIndex, UserItem.wIndex);
              UserItem.btValue[13] := UserItem.btValue[13] and $FE;
              //清除自定义物品名字标记
            end;
            m_ItemList.Delete(i);
            WeightChanged();
          end;
        end;
        Break;
      end;
    end;
  end;                                                                                              // for
end;

//CM_WALK命令的处理

function TPlayObject.ClientWalkXY(wIdent: word; nX, nY: Integer; boLateDelivery:
  Boolean; var dwDelayTime: LongWord): Boolean;                                                     //004CAF08
var
  n14, n18, n1C                         : Integer;
  dwCheckTime                           : LongWord;
  nPinjunTime                           : Integer;
  nCheckTime                            : Integer;
begin
  Result := False;
  dwDelayTime := 0;
  if (not m_boCanWalk) or (m_wShopItemCount > 0) or (m_boCatapultAttackMode) then Exit;

  if not CheckCanOperate(cWalk) then Exit;

  if (not g_Config.boDisableM2SpeedCtrl) then begin
    //10指令时间控制
    if m_nWalkCount = 0 then m_FirstWalkTick := GetTickCount;
    m_nRunCount := 0;
    Inc(m_nWalkCount);
    if m_nWalkCount >= 11 then begin
      nPinjunTime := (GetTickCount - m_FirstWalkTick) div 10;
{$IF USESDK = DEBUG}
      //SysMsg('走10次平均时间:'+inttostr(nPinjunTime),c_blue,t_hint);
{$IFEND}
      m_FirstWalkTick := GetTickCount;
      m_nWalkCount := 0;
      if nPinjunTime < g_Config.n10WalkTIme then begin
        if m_boTestSpeedMode then
          SysMsg(Format('10次走超速!限制:%d,当前:%d', [g_Config.n10WalkTIme, nPinjunTime]), c_Red, t_Hint);
        Exit;
      end;
    end;
  end;

  nCheckTime := GetTickCount - m_dwDoMotaeboMoveTick;
  if nCheckTime < g_Config.dwWalkIntervalTime div 4 then
    Exit;                                                                                           //如果间隔时间小于 600 毫秒
  m_dwDoMotaeboMoveTick := GetTickCount();

  if (not g_Config.boDisableM2SpeedCtrl) and (not boLateDelivery) then begin
    if not CheckActionStatus(wIdent, dwDelayTime) then begin
      m_boFilterAction := False;                                                                    //行动被过滤
      Exit;
    end;
    m_boFilterAction := True;
    dwCheckTime := GetTickCount - m_dwMoveTick;

    if (dwCheckTime < g_Config.dwWalkIntervalTime + m_dwWalkTick) then begin
      if m_dwWalkTick = 0 then
        Inc(m_dwMoveCount);
      dwDelayTime := _Max(0, g_Config.dwWalkIntervalTime - dwCheckTime);
      if dwDelayTime > g_Config.dwWalkIntervalTime div 3 then begin
        if m_dwMoveCount >= 4 then begin
          m_dwMoveTick := GetTickCount();
          m_dwMoveCount := 0;
          dwDelayTime := g_Config.dwWalkIntervalTime div 3;
          if m_boTestSpeedMode then
            SysMsg('走路忙复位!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
        end else
          m_dwMoveCount := 0;
        Exit;
      end else begin
        if m_boTestSpeedMode then
          SysMsg('走路忙!!!' + IntToStr(dwDelayTime), c_Red, t_Hint);
        Exit;
      end;
    end;
  end;
  m_dwWalkTick := 0;

  m_dwMoveTick := GetTickCount();

  m_boMoveSuccess := False;
  n18 := m_nCurrX;
  n1C := m_nCurrY;
  n14 := GetNextDirection(m_nCurrX, m_nCurrY, nX, nY);
  //取得走到目标的方向

  if WalkTo(n14, False) then begin
    if m_boMoveSuccess or ((m_nCurrX = nX) and (m_nCurrY = nY)) then begin
      Result := True;
      RunStepToDamage(1);
    end;
    Dec(m_nHealthTick, 10);
  end else begin
    m_dwMoveCount := 0;
    m_dwMoveCountA := 0;
  end;
end;

procedure TPlayObject.CmdAddGold(Cmd: pTGameCmd; sHumName: string; nCount: Integer);                //004CD550
var
  PlayObject                            : TPlayObject;
  nServerNumber                         : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sHumName = '') or (nCount <= 0) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称  金币数量', c_Red,
      t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    if (PlayObject.m_nGold + nCount) < PlayObject.m_nGoldMax then begin
      Inc(PlayObject.m_nGold, nCount);
    end else begin
      nCount := PlayObject.m_nGoldMax - PlayObject.m_nGold;
      PlayObject.m_nGold := PlayObject.m_nGoldMax;
    end;
    PlayObject.GoldChanged();
    SysMsg(sHumName + '的金币已增加' + IntToStr(nCount) + '.', c_Green, t_Hint);
    if g_boGameLogGold then
      AddGameDataLog('14' + #9 +
        m_sMapName + #9 +
        IntToStr(m_nCurrX) + #9 +
        IntToStr(m_nCurrY) + #9 +
        m_sCharName + #9 +
        sSTRING_GOLDNAME + #9 +
        IntToStr(nCount) + #9 +
        '1' + #9 +
        sHumName);
  end else begin
    if UserEngine.FindOtherServerUser(sHumName, nServerNumber) then begin
      SysMsg(sHumName + ' 现在' + IntToStr(nServerNumber) + '号服务器上', c_Green, t_Hint);
    end else begin
      SysMsg(sHumName + ' 现在不在线!!!', c_Green, t_Hint);
    end;
  end;
end;

procedure TPlayObject.CmdAddGuild(Cmd: pTGameCmd; sGuildName, sGuildChief:
  string);                                                                                          //004CEBA0
var
  human                                 : TPlayObject;
  boAddState                            : Boolean;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if g_Config.nServerNumber <> 0 then begin
    SysMsg('这个命令只能使用在主服务器上', c_Red, t_Hint);
    Exit;
  end;
  if (sGuildName = '') or (sGuildChief = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 行会名称 掌门人名称',
      c_Red, t_Hint);
    Exit;
  end;

  boAddState := False;
  human := UserEngine.GetPlayObject(sGuildChief);
  if human = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sGuildChief]), c_Red,
      t_Hint);
    Exit;
  end;
  if g_GuildManager.MemberOfGuild(sGuildChief) = nil then begin
    if g_GuildManager.AddGuild(sGuildName, sGuildChief) then begin
      UserEngine.SendServerGroupMsg(SS_205, g_Config.nServerNumber, sGuildName + '/' + sGuildChief);
      SysMsg('行会名称: ' + sGuildName + ' 掌门人: ' + sGuildChief, c_Green, t_Hint);
      boAddState := True;
    end;
  end;                                                                                              //004CECB4
  if boAddState then begin
    human.m_MyGuild := g_GuildManager.MemberOfGuild(human.m_sCharName);
    if human.m_MyGuild <> nil then begin
      human.m_sGuildRankName := TGuild(human.m_MyGuild).GetRankName(Self, human.m_nGuildRankNo);
      human.RefShowName();
    end;
  end;                                                                                              //004CED14
end;

procedure TPlayObject.CmdAdjuestExp(Cmd: pTGameCmd; sHumanName, sExp: string);
var
  PlayObject                            : TPlayObject;
  dwExp                                 : LongWord;
  dwOExp                                : LongWord;
resourcestring
  sLogMsg                               = '[经验调整] %s(%s %d -> %d)';
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 经验值', c_Red,
      t_Hint);
    Exit;
  end;
  dwExp := Str_ToInt(sExp, 0);

  PlayObject := UserEngine.GetPlayObject(sHumanName);

  if PlayObject <> nil then begin
    dwOExp := PlayObject.m_Abil.Exp;
    PlayObject.m_Abil.Exp := dwExp;
    PlayObject.HasLevelUp(0);
    SysMsg(PlayObject.m_sCharName + ' 经验调整完成。', c_Green, t_Hint);
    if g_Config.boShowMakeItemMsg then
      MainOutMessage(Format(sLogMsg, [m_sCharName, PlayObject.m_sCharName,
        dwOExp, PlayObject.m_Abil.Exp]));
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdAdjuestLevel(Cmd: pTGameCmd; sHumanName: string;
  nLevel: Integer);
var
  PlayObject                            : TPlayObject;
  nOLevel                               : Integer;
resourcestring
  sLogMsg                               = '[等级调整] %s(%s %d -> %d)';
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumanName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 等级', c_Red,
      t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    nOLevel := PlayObject.m_Abil.level;
    PlayObject.m_Abil.level := _Max(1, _MIN(MAXUPLEVEL, nLevel));
    m_nMagicStatus := GetMagicStatus;
    PlayObject.HasLevelUp(1);
    SysMsg(sHumanName + ' 等级调整完成。', c_Green, t_Hint);
    if g_Config.boShowMakeItemMsg then
      MainOutMessage(Format(sLogMsg, [m_sCharName, PlayObject.m_sCharName,
        nOLevel, PlayObject.m_Abil.level]));
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdAdjustExp(human: TPlayObject; nExp: Integer);                              //004CDDAC
begin
  if (m_btPermissionGM < 6) then Exit;
end;

procedure TPlayObject.CmdAllowGroupReCall(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('此命令用于允许或禁止编组传送功能。', c_Red,
      t_Hint);
    Exit;
  end;

  m_boAllowGroupReCall := not m_boAllowGroupReCall;
  if m_boAllowGroupReCall then
    SysMsg(g_sEnableGroupRecall {'[允许天地合一]'}, c_Green, t_Hint)
  else SysMsg(g_sDisableGroupRecall {'[禁止天地合一]'}, c_Green, t_Hint);
end;

procedure TPlayObject.CmdAnnouncement(Cmd: pTGameCmd; sGuildName: string);
//004CF564
var
  i                                     : Integer;
  Guild                                 : TGuild;
  //PlayObject:TPlayObject;
  sHumanName                            : string;
  nPoint                                : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sGuildName = '') or ((sGuildName <> '') and (sGuildName[1] = '?')) then begin
    SysMsg('查看行会争霸赛结果。', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s 行会名称', [Cmd.sCmd]), c_Red, t_Hint);
    Exit;
  end;

  if not m_PEnvir.m_MapFlag.boFight3 then begin
    SysMsg('此命令不能在当前地图中使用!!!', c_Red, t_Hint);
    Exit;
  end;
  Guild := g_GuildManager.FindGuild(sGuildName);
  if Guild <> nil then begin
    UserEngine.CryCry(RM_CRY, m_PEnvir, m_nCurrX, m_nCurrY, 1000,
      g_Config.btCryMsgFColor, g_Config.btCryMsgBColor,
      Format(' - %s 行会争霸赛结果: ', [Guild.sGuildName]));
    for i := 0 to Guild.TeamFightDeadList.Count - 1 do begin
      nPoint := Integer(Guild.TeamFightDeadList.Objects[i]);
      sHumanName := Guild.TeamFightDeadList.Strings[i];
      UserEngine.CryCry(RM_CRY,
        m_PEnvir,
        m_nCurrX,
        m_nCurrY,
        1000,
        g_Config.btCryMsgFColor,
        g_Config.btCryMsgBColor,
        Format(' - %s  : %d 分/死亡%d次。 ', [sHumanName, HiWord(nPoint),
        LoWord(nPoint)]));
    end;
  end;
  UserEngine.CryCry(RM_CRY,
    m_PEnvir,
    m_nCurrX,
    m_nCurrY,
    1000,
    g_Config.btCryMsgFColor,
    g_Config.btCryMsgBColor,
    Format(' - [%s] : %d 分。', [Guild.sGuildName, Guild.nContestPoint]));
  UserEngine.CryCry(RM_CRY,
    m_PEnvir,
    m_nCurrX,
    m_nCurrY,
    1000,
    g_Config.btCryMsgFColor,
    g_Config.btCryMsgBColor,
    '------------------------------------');
end;

procedure TPlayObject.CmdBackStep(sCmd: string; nType, nCount: Integer);
begin
  if (m_btPermissionGM < 6) then Exit;
  nType := _MIN(nType, 8);
  if nType = 0 then begin
    CharPushed(GetBackDir(m_btDirection), nCount, False);
  end else begin
    CharPushed(Random(nType), nCount, False);
  end;
end;

procedure TPlayObject.CmdBindGameGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
var
  PlayObject                            : TPlayObject;
  Ctr                                   : Char;
resourcestring
  sLogMsg                               = '[调整金币] %s 给:%s %s %d 绑定元宝';
begin
  Ctr := '1';
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCtr <> '') then begin
    Ctr := sCtr[1];
  end;

  if (sHumanName = '') or not (Ctr in ['=', '+', '-']) or (nGold < 0) or (nGold > 200000000) or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, g_sGameCommandGameGoldHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  case sCtr[1] of
    '=': begin
        if nGold > g_Config.nHumanMaxGameGold then begin
          SysMsg(sHumanGameGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        PlayObject.m_nBindGameGold := nGold;
      end;
    '+': begin
        if nGold + PlayObject.m_nBindGameGold > g_Config.nHumanMaxGameGold then begin
          SysMsg(sHumanGameGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        Inc(PlayObject.m_nBindGameGold, nGold);
      end;
    '-': begin
        nGold := _Max(0, PlayObject.m_nBindGameGold - nGold);
        PlayObject.m_nBindGameGold := nGold;
      end;
  end;
  if g_boGameLogGameGold then begin
    AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD,
      PlayObject.m_sMapName,
        PlayObject.m_nCurrX,
        PlayObject.m_nCurrY,
        PlayObject.m_sCharName,
        '绑定元宝',
        nGold,
        sCtr[1],
        m_sCharName]));
  end;
  GameGoldChanged(1);
  PlayObject.SysMsg(Format(g_sGameCommandGameGoldHumanMsg, ['绑定元宝', nGold, PlayObject.m_nBindGameGold, '绑定元宝']), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandGameGoldGMMsg, [sHumanName, '绑定元宝', nGold, PlayObject.m_nBindGameGold, '绑定元宝']), c_Green, t_Hint);

  if g_Config.boShowMakeItemMsg and (m_btPermissionGM >= 6) then
    MainOutMessage(Format(sLogMsg, [m_sCharName, PlayObject.m_sCharName, sCtr[1], nGold]));
end;

procedure TPlayObject.CmdBindGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
var
  PlayObject                            : TPlayObject;
  Ctr                                   : Char;
resourcestring
  sLogMsg                               = '[调整金币] %s 给:%s %s %d 绑定金币';
begin
  Ctr := '1';
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCtr <> '') then begin
    Ctr := sCtr[1];
  end;

  if (sHumanName = '') or not (Ctr in ['=', '+', '-']) or (nGold < 0) or (nGold > 200000000) or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, g_sGameCommandGoldHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  case sCtr[1] of
    '=': begin
        if nGold > g_Config.nHumanMaxGold then begin
          SysMsg(sHumanGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        PlayObject.m_nBindGold := nGold;
      end;
    '+': begin
        if nGold + PlayObject.m_nBindGold > g_Config.nHumanMaxGold then begin
          SysMsg(sHumanGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        Inc(PlayObject.m_nBindGold, nGold);
      end;
    '-': begin
        nGold := _Max(0, PlayObject.m_nBindGold - nGold);
        PlayObject.m_nBindGold := nGold;
      end;
  end;
  if g_boGameLogGold then begin
    AddGameDataLog(Format(g_sGameLogMsg, [LOG_GOLD,
      PlayObject.m_sMapName,
        PlayObject.m_nCurrX,
        PlayObject.m_nCurrY,
        PlayObject.m_sCharName,
        sSTRING_BINDGOLDNAME,
        nGold,
        sCtr[1],
        m_sCharName]));
  end;
  GoldChanged(1);
  PlayObject.SysMsg(Format(g_sGameCommandGameGoldHumanMsg, [sSTRING_BINDGOLDNAME, nGold, PlayObject.m_nBindGold, sSTRING_BINDGOLDNAME]), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandGameGoldGMMsg, [sHumanName, sSTRING_BINDGOLDNAME, nGold, PlayObject.m_nBindGold, sSTRING_BINDGOLDNAME]), c_Green, t_Hint);

  if g_Config.boShowMakeItemMsg and (m_btPermissionGM >= 6) then
    MainOutMessage(Format(sLogMsg, [m_sCharName, PlayObject.m_sCharName, sCtr[1], nGold]));
end;

procedure TPlayObject.CmdBindUseItem(Cmd: pTGameCmd; sHumanName, sItem,
  sType: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  UserItem                              : pTUserItem;
  nItem, nBind                          : Integer;
  ItemBind                              : pTItemBind;
  nItemIdx, nMakeIdex                   : Integer;
  sBindName                             : string;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  nBind := -1;
  nItem := GetUseItemIdx(sItem);
  if CompareText(sType, '帐号') = 0 then nBind := 0;
  if CompareText(sType, '人物') = 0 then nBind := 1;
  if CompareText(sType, 'IP') = 0 then nBind := 2;

  if (nItem < 0) or (nBind < 0) or (sHumanName = '') or ((sHumanName <> '') and
    (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandBindUseItemHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  UserItem := @PlayObject.m_UseItems[nItem];
  if UserItem.wIndex = 0 then begin
    SysMsg(Format(g_sGameCommandBindUseItemNoItemMsg, [sHumanName, sItem]),
      c_Red, t_Hint);
    Exit;
  end;
  nItemIdx := UserItem.wIndex;
  nMakeIdex := UserItem.MakeIndex;
  case nBind of                                                                                     //
    0: begin
        sBindName := PlayObject.m_sUserID;
        for i := 0 to g_ItemBindAccount.Count - 1 do begin
          ItemBind := g_ItemBindAccount.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName,
              sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindAccount.Insert(0, ItemBind);
        SaveItemBindAccount();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
    1: begin
        sBindName := PlayObject.m_sCharName;

        for i := 0 to g_ItemBindCharName.Count - 1 do begin
          ItemBind := g_ItemBindCharName.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName,
              sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindCharName.Insert(0, ItemBind);

        SaveItemBindCharName();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
    2: begin
        sBindName := PlayObject.m_sIPaddr;
        for i := 0 to g_ItemBindIPaddr.Count - 1 do begin
          ItemBind := g_ItemBindIPaddr.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName, sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindIPaddr.Insert(0, ItemBind);

        SaveItemBindIPaddr();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
  end;
end;

procedure TPlayObject.CmdBonuPoint(Cmd: pTGameCmd; sHumName: string; nCount:
  Integer);
var
  PlayObject                            : TPlayObject;
  sMsg                                  : string;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd +
      ' 人物名称 属性点数(不输入为查看点数)', c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumName]), c_Red, t_Hint);
    Exit;
  end;
  if (nCount > 0) then begin
    PlayObject.m_nBonusPoint := nCount;
    PlayObject.SendMsg(Self, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
    Exit;
  end;
  sMsg :=
    Format('未分配点数:%d 已分配点数:(DC:%d MC:%d SC:%d AC:%d MAC:%d HP:%d MP:%d HIT:%d SPEED:%d)',
    [PlayObject.m_nBonusPoint,
    PlayObject.m_BonusAbil.DC,
      PlayObject.m_BonusAbil.MC,
      PlayObject.m_BonusAbil.SC,
      PlayObject.m_BonusAbil.AC,
      PlayObject.m_BonusAbil.MAC,
      PlayObject.m_BonusAbil.HP,
      PlayObject.m_BonusAbil.MP,
      PlayObject.m_BonusAbil.Hit,
      PlayObject.m_BonusAbil.Speed
      ]);
  SysMsg(Format('%s的属性点数为:%s', [sHumName, sMsg]), c_Red, t_Hint);
end;

procedure TPlayObject.CmdChangeAdminMode(sCmd: string; nPermission: Integer;
  sParam1: string; boFlag: Boolean);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;

  m_boAdminMode := boFlag;
  if m_boAdminMode then SysMsg(sGameMasterMode, c_Green, t_Hint)
  else SysMsg(sReleaseGameMasterMode, c_Green, t_Hint);
end;

procedure TPlayObject.CmdChangeAttackMode(nMode: Integer);
var
  OldAttatckMode                        : Integer;
begin
  if m_PEnvir.m_MapFlag.boNoChAttackMode then begin
    SysMsg(sDisableChangeAttackMode, c_Red, t_Hint);
    Exit;
  end;

  OldAttatckMode := m_btAttatckMode;
  if (nMode >= 0) and (nMode <= 7) then
    m_btAttatckMode := nMode
  else begin
{$IF COUNTRYSYSTEM = 1}
    if m_btAttatckMode < HAM_COUNTRY then Inc(m_btAttatckMode)
{$ELSE}
      if m_btAttatckMode < HAM_DEAR then Inc(m_btAttatckMode)
{$IFEND}
      else m_btAttatckMode := HAM_PKATTACK;
  end;
  while (True) do begin
    if g_Config.boShowAttackModeMsg[m_btAttatckMode] then Break;
{$IF COUNTRYSYSTEM = 1}
    if m_btAttatckMode < HAM_COUNTRY then Inc(m_btAttatckMode)
{$ELSE}
      if m_btAttatckMode < HAM_DEAR then Inc(m_btAttatckMode)
{$IFEND}
      else m_btAttatckMode := HAM_PKATTACK;
  end;
  case m_btAttatckMode of
    HAM_PKATTACK: SysMsg(sAttackModeOfRedWhite, c_Green, t_Client);
    //[攻击模式: 红名攻击]
    HAM_ALL: SysMsg(sAttackModeOfAll, c_Green, t_Client);
    //[攻击模式: 全体攻击]
    HAM_PEACE: SysMsg(sAttackModeOfPeaceful, c_Green, t_Client);
    //[攻击模式: 和平攻击]
    HAM_DEAR: SysMsg(sAttackModeOfDear, c_Green, t_Client);
    //[攻击模式: 夫妻攻击]
    HAM_MASTER: SysMsg(sAttackModeOfMaster, c_Green, t_Client);
    //[攻击模式: 师徒攻击]
    HAM_GROUP: SysMsg(sAttackModeOfGroup, c_Green, t_Client);
    //[攻击模式: 编组攻击]
    HAM_GUILD: SysMsg(sAttackModeOfGuild, c_Green, t_Client);
    //[攻击模式: 行会攻击]
{$IF COUNTRYSYSTEM = 1}
    HAM_COUNTRY: if g_Config.boShowAttackModeMsg[m_btAttatckMode] then
        SysMsg(sAttackModeOfCountry, c_Green, t_Client);
    //[攻击模式:国家攻击]
{$IFEND}
  end;
  //元神的攻击模式和主人相同
  if not m_boPneuma and (m_PneumaObject <> nil) then
    m_PneumaObject.m_btAttatckMode := m_btAttatckMode;
end;

procedure TPlayObject.CmdChangeDearName(Cmd: pTGameCmd; sHumanName, sDearName:
  string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (sDearName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 配偶名称(如果为 无 则清除)', c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    if CompareText(sDearName, '无') = 0 then begin
      PlayObject.m_sDearName := '';
      PlayObject.RefShowName;
      if g_Config.boShowScriptActionMsg then
        SysMsg(sHumanName + ' 的配偶名清除成功。', c_Green, t_Hint);
    end else begin
      PlayObject.m_sDearName := sDearName;
      PlayObject.RefShowName;
      if g_Config.boShowScriptActionMsg then
        SysMsg(sHumanName + ' 的配偶名更改成功。', c_Green, t_Hint);
    end;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

//改性别

procedure TPlayObject.CmdChangeGender(Cmd: pTGameCmd; sHumanName, sSex: string);
var
  PlayObject                            : TPlayObject;
  nSex                                  : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  nSex := -1;
  if (sSex = 'Man') or (sSex = '男') or (sSex = '0') then begin
    nSex := 0;
  end;
  if (sSex = 'WoMan') or (sSex = '女') or (sSex = '1') then begin
    nSex := 1;
  end;
  if (sHumanName = '') or (nSex = -1) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 性别(男、女)',
      c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    if PlayObject.m_btGender <> nSex then begin
      PlayObject.m_btGender := nSex;
      PlayObject.FeatureChanged();
      SysMsg(PlayObject.m_sCharName + ' 的性别已改变。', c_Green, t_Hint);
    end else begin
      SysMsg(PlayObject.m_sCharName + ' 的性别未改变!!!', c_Red, t_Hint);
    end;
  end else begin
    SysMsg(sHumanName + '没有在线!!!', c_Red, t_Hint);
  end;
end;

//自定义物品名字

procedure TPlayObject.CmdChangeItemName(sCmd, sMakeIndex, sItemIndex, sItemName:
  string);
var
  nMakeIndex, nItemIndex                : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sMakeIndex = '') or (sItemIndex = '') or (sItemName = '') then begin
    SysMsg('命令格式: @' + sCmd + ' 物品编号 物品ID号 物品名称', c_Red, t_Hint);
    Exit;
  end;
  nMakeIndex := Str_ToInt(sMakeIndex, -1);
  nItemIndex := Str_ToInt(sItemIndex, -1);
  if (nMakeIndex <= 0) or (nItemIndex < 0) then begin
    SysMsg('命令格式: @' + sCmd + ' 物品编号 物品ID号 物品名称', c_Red, t_Hint);
    Exit;
  end;
  if ItemUnit.AddCustomItemName(nMakeIndex, nItemIndex, sItemName) then begin
    ItemUnit.SaveCustomItemName();
    SysMsg('物品名称设置成功。', c_Green, t_Hint);
    Exit;
  end;

  SysMsg('此物品,已经设置了其它的名称!!!', c_Red, t_Hint);
end;

//改变职业

procedure TPlayObject.CmdChangeJob(Cmd: pTGameCmd; sHumanName, sJobName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  if (sHumanName = '') or (sJobName = '') then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandChangeJobHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    if CompareText(sJobName, 'Warr') = 0 then PlayObject.m_btJob := 0;
    if CompareText(sJobName, 'Wizard') = 0 then PlayObject.m_btJob := 1;
    if CompareText(sJobName, 'Taos') = 0 then PlayObject.m_btJob := 2;
    if CompareText(sJobName, 'Goblin') = 0 then PlayObject.m_btJob := 3;
    PlayObject.HasLevelUp(0);
    PlayObject.SysMsg(g_sGameCommandChangeJobHumanMsg, c_Green, t_Hint);
    SysMsg(Format(g_sGameCommandChangeJobMsg, [sHumanName]), c_Green, t_Hint);
    if not m_boPneuma then begin
      PlayObject.SendUpdateDelayMsg(PlayObject, RM_REFRESHRANK, 0, 0, 0, 0, '', 1000);
      PlayObject.SendUpdateDelayMsg(PlayObject, RM_REFRESHRANK, 0, 5, 0, 0, '', 1000);
    end else begin
      PlayObject.SendUpdateDelayMsg(PlayObject, RM_REFRESHRANK, 0, 1, 0, 0, '', 1000);
    end;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

//修改等级

procedure TPlayObject.CmdChangeLevel(Cmd: pTGameCmd; sParam1: string);
var
  nOLevel                               : Integer;
  nLevel                                : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  nLevel := Str_ToInt(sParam1, 1);
  nOLevel := m_Abil.level;

  m_Abil.level := _MIN(MAXUPLEVEL, nLevel);
  HasLevelUp(m_Abil.level - 1);
  if g_Config.boShowMakeItemMsg then begin
    MainOutMessage(Format(g_sGameCommandLevelConsoleMsg, [m_sCharName, nOLevel,
      m_Abil.level]));
  end;
end;

procedure TPlayObject.CmdChangeMasterName(Cmd: pTGameCmd; sHumanName,
  sMasterName, sIsMaster: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (sMasterName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 师徒名称(如果为 无 则清除)', c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    ChangeMasterName(sHumanName, sMasterName, sIsMaster = '1');
    if g_Config.boShowScriptActionMsg then
      SysMsg(sHumanName + ' 的师徒名更改成功。', c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdChangeObMode(sCmd: string; nPermission: Integer;
  sParam1: string; boFlag: Boolean);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  if boFlag then begin
    SendRefMsg(RM_DISAPPEAR, 0, 0, 0, 0, '');
    //01/21 强行发送刷新数据到客户端,解决GM登录隐身有影子问题
  end;
  m_boObMode := boFlag;
  if m_boObMode then
    SysMsg(sObserverMode, c_Green, t_Hint)
  else
    SysMsg(g_sReleaseObserverMode, c_Green, t_Hint);
end;

procedure TPlayObject.CmdChangeSabukLord(Cmd: pTGameCmd; sCASTLENAME,
  sGuildName: string; boFlag: Boolean);                                                             //004CFE1C
var
  Guild                                 : TGuild;
  Castle                                : TUserCastle;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  if (sCASTLENAME = '') or (sGuildName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 城堡名称 行会名称', c_Red, t_Hint);
    Exit;
  end;
  Castle := g_CastleManager.Find(sCASTLENAME);
  if Castle = nil then begin
    SysMsg(Format(g_sGameCommandSbkGoldCastleNotFoundMsg, [sCASTLENAME]), c_Red, t_Hint);
    Exit;
  end;

  Guild := g_GuildManager.FindGuild(sGuildName);
  if Guild <> nil then begin
    //4CFEC7
    AddGameDataLog('27' + #9 +
      Castle.m_sOwnGuild + #9 +
      '0' + #9 +
      '1' + #9 +
      'sGuildName' + #9 +
      m_sCharName + #9 +
      '0' + #9 +
      '1' + #9 +
      '0');
    Castle.GetCastle(Guild);
    if boFlag then
      UserEngine.SendServerGroupMsg(SS_211, g_Config.nServerNumber, sGuildName);
    SysMsg(Castle.m_sName + ' 所属行会已经更改为 ' + sGuildName,
      c_Green, t_Hint);
  end else begin
    SysMsg('行会 ' + sGuildName + '还没建立!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdChangeSalveStatus;
var
  i, nCount                             : Integer;
begin
  nCount := 0;
  if m_SlaveList.Count > 0 then begin
    m_boSlaveRelax := not m_boSlaveRelax;
    if (m_TorDDM.Tiger.DB.Dragon > 0) then m_boTigerRelax := m_boSlaveRelax;

    if m_PneumaObject <> nil then
      m_PneumaObject.m_boSlaveRelax := m_boSlaveRelax;

    for i := 0 to m_SlaveList.Count - 1 do begin
      if TBaseObject(m_SlaveList[i]).IsTiger and (m_TorDDM.Tiger.DB.Dragon = 0) then Continue;

      TBaseObject(m_SlaveList[i]).m_boSlaveRelax := m_boSlaveRelax;
      if m_boSlaveRelax then
        TBaseObject(m_SlaveList[i]).DelTargetCreat;

      Inc(nCount);
    end;
  end else if (m_PneumaObject <> nil) and (m_PneumaObject.m_SlaveList.Count > 0) then begin
    m_boSlaveRelax := not m_boSlaveRelax;
    m_PneumaObject.m_boSlaveRelax := m_boSlaveRelax;
    for i := 0 to m_PneumaObject.m_SlaveList.Count - 1 do begin
      if TBaseObject(m_PneumaObject.m_SlaveList[i]).IsTiger then Continue;

      TBaseObject(m_PneumaObject.m_SlaveList[i]).m_boSlaveRelax := m_boSlaveRelax;
      if m_boSlaveRelax then
        TBaseObject(m_PneumaObject.m_SlaveList[i]).DelTargetCreat;

      Inc(nCount);
    end;
  end;
  if nCount > 0 then begin
    if m_boSlaveRelax then
      SysMsg(sPetRest, c_Green, t_Hint)
    else
      SysMsg(sPetAttack, c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdChangeSuperManMode(sCmd: string; nPermission: Integer;
  sParam1: string; boFlag: Boolean);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  m_boSuperMan := boFlag;
  if m_boSuperMan then SysMsg(sSupermanMode, c_Green, t_Hint)
  else SysMsg(sReleaseSupermanMode, c_Green, t_Hint);
end;

procedure TPlayObject.CmdChangeTigerStatus;
begin
  if (m_Tiger <> nil) and (not m_Tiger.m_boDeath) and (not m_Tiger.m_boGhost) and (m_TorDDM.Tiger.DB.Dragon = 0) then begin
    m_boTigerRelax := not m_boTigerRelax;
    if m_boTigerRelax then begin
      SysMsg('虎王休息', c_Green, t_Hint);
      SendDefMessage(SM_TIGERSTATUS, 0, 0, 0, 0, '');
      m_Tiger.DelTargetCreat;
    end else begin
      SysMsg('虎王攻击', c_Green, t_Hint);
      SendDefMessage(SM_TIGERSTATUS, 0, 1, 0, 0, '');
    end;
    m_Tiger.m_boTigerRelax := m_boTigerRelax;
  end;
end;

procedure TPlayObject.CmdChangeUserFull(sCmd, sUserCount: string);
var
  nCount                                : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  nCount := Str_ToInt(sUserCount, -1);
  if (sUserCount = '') or (nCount < 1) or ((sUserCount <> '') and (sUserCount[1]
    = '?')) then begin
    SysMsg('设置服务器最高上线人数。', c_Red, t_Hint);
    SysMsg('命令格式: @' + sCmd + ' 人数', c_Red, t_Hint);
    Exit;
  end;
  g_Config.nUserFull := nCount;
  SysMsg(Format('服务器上线人数限制: %d', [nCount]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdChangeZenFastStep(sCmd, sFastStep: string);
var
  nFastStep                             : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  nFastStep := Str_ToInt(sFastStep, -1);
  if (sFastStep = '') or (nFastStep < 1) or ((sFastStep <> '') and (sFastStep[1]
    = '?')) then begin
    SysMsg('设置怪物行动速度。', c_Red, t_Hint);
    SysMsg('命令格式: @' + sCmd + ' 速度', c_Red, t_Hint);
    Exit;
  end;
  g_Config.nZenFastStep := nFastStep;
  SysMsg(Format('怪物行动速度: %d', [nFastStep]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdClearBagItem(Cmd: pTGameCmd; sHumanName: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  UserItem                              : pTUserItem;
  DelList                               : TStringList;
begin
  DelList := nil;
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '人物名称']), c_Red,
      t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;

  for i := 0 to PlayObject.m_ItemList.Count - 1 do begin
    UserItem := PlayObject.m_ItemList.Items[i];
    //if DelList = nil then DelList := TStringList.Create;
    //DelList.AddObject(UserEngine.GetStdItemName(UserItem.wIndex), TObject(UserItem.MakeIndex));
    SendDelItems(UserItem);
    Dispose(UserItem);
  end;
  PlayObject.m_ItemList.Clear;
  WeightChanged;
  //  if DelList <> nil then begin
  //    PlayObject.SendMsg(PlayObject, RM_SENDDELITEMLIST, 0, Integer(DelList), 0, 0, '');
  //  end;
end;

procedure TPlayObject.CmdClearHumanPassword(sCmd: string; nPermission: Integer;
  sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < nPermission) then Exit;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg('清除玩家的仓库密码!!!', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s 人物名称', [sCmd]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    Exit;
  end;
  PlayObject.m_boPasswordLocked := False;
  PlayObject.m_boUnLockStoragePwd := False;
  PlayObject.m_sStoragePwd := '';
  PlayObject.SysMsg('你的保护密码已被清除!!!', c_Green, t_Hint);
  SysMsg(Format('%s的保护密码已被清除!!!', [sHumanName]),
    c_Green, t_Hint);
end;

procedure TPlayObject.CmdClearMapMonster(Cmd: pTGameCmd; sMapName, sMonName,
  sItems, sGhost: string);
var
  i, ii                                 : Integer;
  MonList                               : TList;
  Envir                                 : TEnvirnoment;
  nMonCount                             : Integer;
  boKillAll                             : Boolean;
  boKillAllMap                          : Boolean;
  boNotItem                             : Boolean;
  boMakeGhost                           : Boolean;
  BaseObject                            : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMapName = '') or (sMonName = '') or (sItems = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd +
      ' 地图号(* 为所有) 怪物名称(* 为所有) 掉物品(0,1) 清理尸体(0,1)',
      c_Red, t_Hint);
    Exit;
  end;
  boKillAll := False;
  boKillAllMap := False;
  boNotItem := True;
  boMakeGhost := False;
  nMonCount := 0;
  Envir := nil;
  if sMonName = '*' then boKillAll := True;
  if sMapName = '*' then boKillAllMap := True;
  if sItems = '1' then boNotItem := False;
  if sGhost = '1' then boMakeGhost := True;

  MonList := TList.Create;
  if boKillAllMap then begin
    for i := 0 to g_MapManager.Count - 1 do begin
      Envir := TEnvirnoment(g_MapManager.Values[g_MapManager.Keys[i]]);
      if (Envir <> nil) then begin
        MonList.Clear;
        UserEngine.GetMapMonster(Envir, MonList);
        for ii := 0 to MonList.Count - 1 do begin
          BaseObject := TBaseObject(MonList.Items[ii]);
          if boKillAll or (CompareText(sMonName, BaseObject.m_sCharName) = 0) then begin
            BaseObject.m_nHealthTick := 0;
            BaseObject.m_boNoItem := boNotItem;
            if boMakeGhost then BaseObject.MakeGhost else BaseObject.Die;
            Inc(nMonCount);
          end;
        end;
      end;
    end;
  end else begin
    Envir := g_MapManager.FindMap(sMapName);
    if (Envir <> nil) then begin
      MonList.Clear;
      UserEngine.GetMapMonster(Envir, MonList);
      for ii := 0 to MonList.Count - 1 do begin
        BaseObject := TBaseObject(MonList.Items[ii]);
        if boKillAll or (CompareText(sMonName, BaseObject.m_sCharName) = 0) then begin
          BaseObject.m_nHealthTick := 0;
          BaseObject.m_boNoItem := boNotItem;
          if boMakeGhost then BaseObject.MakeGhost else BaseObject.Die;
          Inc(nMonCount);
        end;
      end;
    end;
  end;
  MonList.free;
  if Envir = nil then begin
    SysMsg('输入的地图不存在!!!', c_Red, t_Hint);
    Exit;
  end;

  SysMsg('已清除怪物数: ' + IntToStr(nMonCount), c_Red, t_Hint);
end;

procedure TPlayObject.CmdClearMission(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称)', c_Red, t_Hint);
    Exit;
  end;
  if sHumanName[1] = '?' then begin
    SysMsg('此命令用于清除人物的任务标志。', c_Blue, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format('%s不在线,或在其它服务器上!!', [sHumanName]),
      c_Red, t_Hint);
    Exit;
  end;
  FillChar(PlayObject.m_QuestFlag, SizeOf(TQuestFlag), #0);
  SysMsg(Format('%s的任务标志已经全部清零。', [sHumanName]),
    c_Green, t_Hint);
end;

procedure TPlayObject.CmdContestPoint(Cmd: pTGameCmd; sGuildName: string);
//004CEF08
var
  //I: Integer;
  Guild                                 : TGuild;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sGuildName = '') or ((sGuildName <> '') and (sGuildName[1] = '?')) then begin
    SysMsg('查看行会战的得分数。', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s 行会名称', [Cmd.sCmd]), c_Red, t_Hint);
    Exit;
  end;
  Guild := g_GuildManager.FindGuild(sGuildName);
  if Guild <> nil then begin
    SysMsg(Format('%s 的得分为: %d', [sGuildName, Guild.nContestPoint]),
      c_Green, t_Hint);
  end else begin
    SysMsg(Format('行会: %s 不存在!!!', [sGuildName]), c_Green,
      t_Hint);
  end;
end;

procedure TPlayObject.CmdCreditPoint(Cmd: pTGameCmd; sHumanName, sCtr: string;
  nPoint: Integer);
var
  PlayObject                            : TPlayObject;
  Ctr                                   : Char;
  nCreditPoint                          : Integer;
begin
  Ctr := '1';
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCtr <> '') then begin
    Ctr := sCtr[1];
  end;

  if (sHumanName = '') or not (Ctr in ['=', '+', '-']) or (nPoint < 0) or (nPoint > High(byte)) or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandCreditPointHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  case sCtr[1] of
    '=': begin
        PlayObject.m_wCreditPoint := nPoint;
      end;
    '+': begin
        if (PlayObject.m_wCreditPoint + nPoint) > High(word) then
          PlayObject.m_wCreditPoint := High(word)
        else
          PlayObject.m_wCreditPoint := PlayObject.m_wCreditPoint + nPoint;
      end;
    '-': begin
        if (PlayObject.m_wCreditPoint - nPoint) < 0 then
          PlayObject.m_wCreditPoint := 0
        else
          PlayObject.m_wCreditPoint := PlayObject.m_wCreditPoint - nPoint;
      end;
  end;

  PlayObject.SendUpdateMsg(PlayObject, RM_SUBABILITY, 0, 0, 0, 0, '');

  PlayObject.SysMsg(Format(g_sGameCommandCreditPointHumanMsg, [nPoint, PlayObject.m_wCreditPoint]), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandCreditPointGMMsg, [sHumanName, nPoint,
    PlayObject.m_wCreditPoint]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdDearRecall(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('命令格式: @' + sCmd +
      ' (夫妻传送,将对方传送到自己身边,对方必须允许传送。)',
      c_Green, t_Hint);
    Exit;
  end;
  if m_sDearName = '' then begin
    SysMsg('你没有结婚!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_PEnvir.m_MapFlag.boNODEARRECALL then begin
    SysMsg('本地图禁止夫妻传送!!!', c_Red, t_Hint);
    Exit;
  end;

  if (m_DearHuman = nil) or m_DearHuman.m_boGhost or m_DearHuman.m_boDeath then begin
    if m_btGender = 0 then begin
      SysMsg('你的老婆不在线!!!', c_Red, t_Hint);
    end else begin
      SysMsg('你的老公不在线!!!', c_Red, t_Hint);
    end;
    Exit;
  end;
  if GetTickCount - m_dwDearRecallTick < 10000 then begin
    SysMsg('稍等会儿才能再次使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_boArrow then begin
    SysMsg('您正在执行任务,目前无法使用此功能!!!',
      c_Red, t_Hint);
    Exit;
  end;

  m_dwDearRecallTick := GetTickCount();
  if m_DearHuman.m_boCanDearRecall then begin
    RecallHuman(m_DearHuman.m_sCharName, $20);
    SendRefMsg(RM_510, 1, 0, $20, 0, '');
    m_DearHuman.SendDelayMsg(Self, RM_510, 1, 0, $20, 0, '', 100);
  end else begin
    SysMsg(m_DearHuman.m_sCharName + ' 不允许传送!!!', c_Red,
      t_Hint);
    Exit;
  end;

end;

procedure TPlayObject.CmdDelBonuPoint(Cmd: pTGameCmd; sHumName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称', c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    FillChar(PlayObject.m_BonusAbil, SizeOf(TNakedAbility), #0);
    PlayObject.m_nBonusPoint := 0;
    PlayObject.SendMsg(PlayObject, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
    PlayObject.HasLevelUp(0);
    PlayObject.SysMsg('分配点数已清除!!!', c_Red, t_Hint);
    SysMsg(sHumName + ' 的分配点数已清除.', c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdDelDenyAccountLogon(Cmd: pTGameCmd; sAccount,
  sFixDeny: string);
var
  i                                     : Integer;
  boDelete                              : Boolean;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sAccount = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 登录帐号', c_Red, t_Hint);
    Exit;
  end;
  boDelete := False;
  g_DenyAccountList.Lock;
  try
    for i := g_DenyAccountList.Count - 1 downto 0 do begin
      if CompareText(sAccount, g_DenyAccountList.Strings[i]) = 0 then begin
        if Integer(g_DenyAccountList.Objects[i]) <> 0 then
          SaveDenyAccountList;
        g_DenyAccountList.Delete(i);
        SysMsg(sAccount + '已从禁止登录帐号列表中删除。', c_Green,
          t_Hint);
        boDelete := True;
        Break;
      end;
    end;
  finally
    g_DenyAccountList.UnLock;
  end;
  if not boDelete then
    SysMsg(sAccount + '没有被禁止登录。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdDelDenyCharNameLogon(Cmd: pTGameCmd; sCharName,
  sFixDeny: string);
var
  i                                     : Integer;
  boDelete                              : Boolean;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sCharName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称', c_Red, t_Hint);
    Exit;
  end;
  boDelete := False;
  g_DenyChrNameList.Lock;
  try
    for i := g_DenyChrNameList.Count - 1 downto 0 do begin
      if CompareText(sCharName, g_DenyChrNameList.Strings[i]) = 0 then begin
        if Integer(g_DenyChrNameList.Objects[i]) <> 0 then
          SaveDenyChrNameList;
        g_DenyChrNameList.Delete(i);
        SysMsg(sCharName + '已从禁止登录人物列表中删除。',
          c_Green, t_Hint);
        boDelete := True;
        Break;
      end;
    end;
  finally
    g_DenyChrNameList.UnLock;
  end;
  if not boDelete then
    SysMsg(sCharName + '没有被禁止登录。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdDelDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr,
  sFixDeny: string);
var
  i                                     : Integer;
  boDelete                              : Boolean;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sIPaddr = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' IP地址', c_Red, t_Hint);
    Exit;
  end;
  boDelete := False;
  g_DenyIPAddrList.Lock;
  try
    for i := g_DenyIPAddrList.Count - 1 downto 0 do begin
      if CompareText(sIPaddr, g_DenyIPAddrList.Strings[i]) = 0 then begin
        if Integer(g_DenyIPAddrList.Objects[i]) <> 0 then
          SaveDenyIPAddrList;
        g_DenyIPAddrList.Delete(i);
        SysMsg(sIPaddr + '已从禁止登录IP列表中删除。', c_Green,
          t_Hint);
        boDelete := True;
        Break;
      end;
    end;
  finally
    g_DenyIPAddrList.UnLock;
  end;
  if not boDelete then
    SysMsg(sIPaddr + '没有被禁止登录。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdDeleteItem(Cmd: pTGameCmd; sHumanName, sItemName:
  string; nCount: Integer);                                                                         //004CDFF8
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  nItemCount                            : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (sItemName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 物品名称 数量)',
      c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  nItemCount := 0;
  for i := PlayObject.m_ItemList.Count - 1 downto 0 do begin
    UserItem := PlayObject.m_ItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (StdItem <> nil) and (CompareText(sItemName, StdItem.Name) = 0) then begin
      PlayObject.SendDelItems(UserItem);
      Dispose(UserItem);
      PlayObject.m_ItemList.Delete(i);
      Inc(nItemCount);
      if nItemCount >= nCount then Break;
    end;
  end;
end;

procedure TPlayObject.CmdDelGold(Cmd: pTGameCmd; sHumName: string; nCount:
  Integer);                                                                                         //004CD27C
var
  PlayObject                            : TPlayObject;
  nServerNumber                         : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumName = '') or (nCount <= 0) then Exit;
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    if PlayObject.m_nGold > nCount then begin
      Dec(PlayObject.m_nGold, nCount);
    end else begin
      nCount := PlayObject.m_nGold;
      PlayObject.m_nGold := 0;
    end;
    PlayObject.GoldChanged();
    SysMsg(sHumName + '的金币已减少' + IntToStr(nCount) + '.', c_Green, t_Hint);

    if g_boGameLogGold then
      AddGameDataLog('5' + #9 +
        m_sMapName + #9 +
        IntToStr(m_nCurrX) + #9 +
        IntToStr(m_nCurrY) + #9 +
        m_sCharName + #9 +
        sSTRING_GOLDNAME + #9 +
        IntToStr(nCount) + #9 +
        '1' + #9 +
        sHumName);
  end else begin
    if UserEngine.FindOtherServerUser(sHumName, nServerNumber) then begin
      SysMsg(sHumName + '现在' + IntToStr(nServerNumber) + '号服务器上', c_Green, t_Hint);
    end else begin
      SysMsg(sHumName + '现在不在线!!!', c_Green, t_Hint);
    end;
  end;
end;

procedure TPlayObject.CmdDelGuild(Cmd: pTGameCmd; sGuildName: string);                              //004CEDEC
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if g_Config.nServerNumber <> 0 then begin
    SysMsg('只能在主服务器上才可以使用此命令删除行会!!!', c_Red, t_Hint);
    Exit;
  end;
  if sGuildName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 行会名称', c_Red, t_Hint);
    Exit;
  end;
  if g_GuildManager.DelGuild(sGuildName) then begin
    UserEngine.SendServerGroupMsg(SS_206, g_Config.nServerNumber, sGuildName);
  end else begin
    SysMsg('没找到' + sGuildName + '这个行会!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdDelNpc(sCmd: string; nPermission: Integer; sParam1:
  string);
var
  BaseObject                            : TBaseObject;
  i                                     : Integer;
resourcestring
  sDelOK                                = '删除NPC成功...';
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  BaseObject := GetPoseCreate();
  if BaseObject <> nil then begin
    for i := 0 to UserEngine.m_MerchantList.Count - 1 do begin
      if TBaseObject(UserEngine.m_MerchantList.Items[i]) = BaseObject then begin
        BaseObject.m_boGhost := True;
        BaseObject.m_dwGhostTick := GetTickCount();
        BaseObject.SendRefMsg(RM_DISAPPEAR, 0, 0, 0, 0, '');
        SysMsg(sDelOK, c_Red, t_Hint);
        Exit;
      end;
    end;
    for i := 0 to UserEngine.QuestNPCList.Count - 1 do begin
      if TBaseObject(UserEngine.QuestNPCList.Items[i]) = BaseObject then begin
        BaseObject.m_boGhost := True;
        BaseObject.m_dwGhostTick := GetTickCount();
        BaseObject.SendRefMsg(RM_DISAPPEAR, 0, 0, 0, 0, '');
        SysMsg(sDelOK, c_Red, t_Hint);
        Exit;
      end;
    end;
  end;
  SysMsg(g_sGameCommandDelNpcMsg, c_Red, t_Hint);
end;

procedure TPlayObject.CmdDelSkill(Cmd: pTGameCmd; sHumanName, sSkillName:
  string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  boDelAll                              : Boolean;
  UserMagic                             : pTUserMagic;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (sSkillName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 技能名称)', c_Red,
      t_Hint);
    Exit;
  end;
  if CompareText(sSkillName, 'All') = 0 then boDelAll := True
  else boDelAll := False;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;

  if boDelAll then begin
    for i := PlayObject.m_MagicList.Count - 1 downto 0 do begin
      UserMagic := PlayObject.m_MagicList.Items[i];
      if UserMagic.btType = MAG_STUDY then begin
        PlayObject.SendDelMagic(UserMagic);
        PlayObject.m_MagicList.Delete(i);
        Dispose(UserMagic);
      end;
    end;
  end else begin
    if PlayObject.DelItemSkill(sSkillName) then begin
      PlayObject.SysMsg(Format('技能%s已删除。', [sSkillName]), c_Green, t_Hint);
      SysMsg(Format('%s的技能%s已删除。', [sHumanName, sSkillName]), c_Green, t_Hint);
    end;
  end;

  PlayObject.RecalcHitSpeed;
  RecalcAbilitys();
  SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
end;

procedure TPlayObject.CmdDenyAccountLogon(Cmd: pTGameCmd; sAccount, sFixDeny:
  string);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sAccount = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 登录帐号 是否永久封(0,1)',
      c_Red, t_Hint);
    Exit;
  end;
  g_DenyAccountList.Lock;
  try
    if (sFixDeny <> '') and (sFixDeny[1] = '1') then begin
      g_DenyAccountList.AddObject(sAccount, TObject(1));
      SaveDenyAccountList();
      SysMsg(sAccount + '已加入禁止登录帐号列表', c_Green, t_Hint);
    end else begin
      g_DenyAccountList.AddObject(sAccount, TObject(0));
      SysMsg(sAccount + '已加入临时禁止登录帐号列表', c_Green,
        t_Hint);
    end;
  finally
    g_DenyAccountList.UnLock;
  end;
end;

procedure TPlayObject.CmdDenyCharNameLogon(Cmd: pTGameCmd; sCharName, sFixDeny:
  string);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sCharName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 是否永久封(0,1)',
      c_Red, t_Hint);
    Exit;
  end;
  g_DenyChrNameList.Lock;
  try
    if (sFixDeny <> '') and (sFixDeny[1] = '1') then begin
      g_DenyChrNameList.AddObject(sCharName, TObject(1));
      SaveDenyChrNameList();
      SysMsg(sCharName + '已加入禁止人物列表', c_Green, t_Hint);
    end else begin
      g_DenyChrNameList.AddObject(sCharName, TObject(0));
      SysMsg(sCharName + '已加入临时禁止人物列表', c_Green, t_Hint);
    end;
  finally
    g_DenyChrNameList.UnLock;
  end;
end;

procedure TPlayObject.CmdDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr, sFixDeny:
  string);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sIPaddr = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' IP地址 是否永久封(0,1)',
      c_Red, t_Hint);
    Exit;
  end;
  g_DenyIPAddrList.Lock;
  try
    if (sFixDeny <> '') and (sFixDeny[1] = '1') then begin
      g_DenyIPAddrList.AddObject(sIPaddr, TObject(1));
      SaveDenyIPAddrList();
      SysMsg(sIPaddr + '已加入禁止登录IP列表', c_Green, t_Hint);
    end else begin
      g_DenyIPAddrList.AddObject(sIPaddr, TObject(0));
      SysMsg(sIPaddr + '已加入临时禁止登录IP列表', c_Green, t_Hint);
    end;
  finally
    g_DenyIPAddrList.UnLock;
  end;
end;

procedure TPlayObject.CmdDisableFilter(sCmd, sParam1: string);
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sParam1 <> '') and (sParam1[1] = '?') then begin
    SysMsg('启用/禁止文字过滤功能。', c_Red, t_Hint);
    Exit;
  end;
  boFilterWord := not boFilterWord;
  if boFilterWord then begin
    SysMsg('已启用文字过滤。', c_Green, t_Hint);
  end else begin
    SysMsg('已禁止文字过滤。', c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdDisableSendMsg(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumanName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称', c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    PlayObject.m_boFilterSendMsg := True;
  end;
  g_DisableSendMsgList.Add(sHumanName);
  SaveDisableSendMsgList();
  SysMsg(sHumanName + ' 已加入禁言列表。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdDisableSendMsgList(Cmd: pTGameCmd);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if g_DisableSendMsgList.Count <= 0 then begin
    SysMsg('禁言列表为空!!!', c_Red, t_Hint);
    Exit;
  end;

  SysMsg('禁言列表:', c_Blue, t_Hint);
  for i := 0 to g_DisableSendMsgList.Count - 1 do begin
    SysMsg(g_DisableSendMsgList.Strings[i], c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdEnableSendMsg(Cmd: pTGameCmd; sHumanName: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumanName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称', c_Red, t_Hint);
    Exit;
  end;
  for i := g_DisableSendMsgList.Count - 1 downto 0 do begin
    if CompareText(sHumanName, g_DisableSendMsgList.Strings[i]) = 0 then begin
      PlayObject := UserEngine.GetPlayObject(sHumanName);
      if PlayObject <> nil then begin
        PlayObject.m_boFilterSendMsg := False;
      end;
      g_DisableSendMsgList.Delete(i);
      SaveDisableSendMsgList();
      SysMsg(sHumanName + ' 已从禁言列表中删除。', c_Green, t_Hint);
      Exit;
    end;
  end;
  SysMsg(sHumanName + ' 没有被禁言!!!', c_Red, t_Hint);
end;

procedure TPlayObject.CmdEndContest(Cmd: pTGameCmd; sParam1: string);                               //004CF364
var
  i, ii                                 : Integer;
  List10, List14                        : TList;
  PlayObject, PlayObjectA               : TPlayObject;
  bo19                                  : Boolean;
  //s20:String;
  Guild                                 : TGuild;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg('结束行会争霸赛。', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s', [Cmd.sCmd]), c_Red, t_Hint);
    Exit;
  end;

  if not m_PEnvir.m_MapFlag.boFight3 then begin
    SysMsg('此命令不能在当前地图中使用!!!', c_Red, t_Hint);
    Exit;
  end;
  List10 := TList.Create;
  List14 := TList.Create;
  UserEngine.GetMapRageHuman(m_PEnvir, m_nCurrX, m_nCurrY, 1000, List10);
  for i := 0 to List10.Count - 1 do begin
    PlayObject := TPlayObject(List10.Items[i]);
    if not PlayObject.m_boObMode or not PlayObject.m_boAdminMode then begin
      if PlayObject.m_MyGuild = nil then Continue;
      bo19 := False;
      for ii := 0 to List14.Count - 1 do begin
        PlayObjectA := TPlayObject(List14.Items[ii]);
        if PlayObject.m_MyGuild = PlayObjectA.m_MyGuild then
          bo19 := True;
      end;
      if not bo19 then begin
        List14.Add(PlayObject.m_MyGuild);
      end;
    end;
  end;
  for i := 0 to List14.Count - 1 do begin
    Guild := TGuild(List14.Items[i]);
    Guild.EndTeamFight();
    UserEngine.CryCry(RM_CRY, m_PEnvir, m_nCurrX, m_nCurrY, 1000,
      g_Config.btCryMsgFColor, g_Config.btCryMsgBColor,
      Format(' - %s 行会争霸赛已结束。', [Guild.sGuildName]));
  end;
  List10.free;
  List14.free;
end;

procedure TPlayObject.CmdEndGuild;                                                                  //4D1A44
begin
  if (m_MyGuild <> nil) then begin
    if (m_nGuildRankNo > 1) then begin
      if TGuild(m_MyGuild).IsMember(m_sCharName) and
        TGuild(m_MyGuild).DelMember(m_sCharName) then begin
        SysMsg('你已经退出行会。', c_Green, t_Hint);
      end;
    end else begin
      SysMsg('行会掌门人不能这样退出行会!!!', c_Red, t_Hint);
    end;
  end else begin
    if g_Config.boOldClientShowHiLevel then
      SysMsg('你都没加入行会!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdFireBurn(nInt, nTime, nn: Integer);
var
  FireBurnEvent                         : TFireBurnEvent;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (nInt = 0) or (nTime = 0) or (nn = 0) then begin
    SysMsg('命令格式: @' + g_GameCommand.FIREBURN.sCmd + ' nInt nTime nN',
      c_Red, t_Hint);
    Exit;
  end;
  FireBurnEvent := TFireBurnEvent.Create(Self, m_nCurrX, m_nCurrY, nInt, nTime,
    nn);

  g_EventManager.AddEvent(FireBurnEvent);
end;

procedure TPlayObject.CmdForcedWallconquestWar(Cmd: pTGameCmd; sCASTLENAME:
  string);
var
  Castle                                : TUserCastle;
  s20                                   : string;
  AttackerInfo                          : pTAttackerInfo;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  if sCASTLENAME = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 城堡名称', c_Red, t_Hint);
    Exit;
  end;

  Castle := g_CastleManager.Find(sCASTLENAME);
  if Castle <> nil then begin
    if Castle.m_boUnderWar or (Castle.m_btForceStartWar <> 0) then
      Castle.m_btForceStartWar := 2
    else
      Castle.m_btForceStartWar := 1;
    l_dwRunTimeTick := 0;
  end else begin
    SysMsg(Format(g_sGameCommandSbkGoldCastleNotFoundMsg, [sCASTLENAME]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdFreePenalty(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandFreePKHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject.m_nPkPoint := 0;
  PlayObject.RefNameColor();
  PlayObject.SysMsg(g_sGameCommandFreePKHumanMsg, c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandFreePKMsg, [sHumanName]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdFriendRecall(sCmd, sParam: string);
var
  i                                     : Integer;
  human                                 : TPlayObject;
begin
  if (sParam = '') or (sParam[1] = '?') then begin
    SysMsg('命令格式: @' + sCmd +
      ' 好友名字(好友传送,可以把你的好友传送到自己身边,好友必须允许传送。)',
      c_Green, t_Hint);
    Exit;
  end;

  if m_FriendsList.Count = 0 then begin
    SysMsg('你还没有好友!!!', c_Red, t_Hint);
    Exit;
  end;

  if m_PEnvir.m_MapFlag.boNOFRIENDRECALL then begin
    SysMsg('本地图禁止好友传送!!!', c_Red, t_Hint);
    Exit;
  end;

  if GetTickCount - m_dwGroupRcallTick < 10000 then begin
    SysMsg('稍等伙才能再次使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_boArrow then begin
    SysMsg('您正在执行任务,目前无法使用此功能!!!',
      c_Red, t_Hint);
    Exit;
  end;
  for i := 0 to m_FriendsList.Count - 1 do begin
    if m_FriendsList[i] = sParam then begin
      human := UserEngine.GetPlayObject(sParam);
      if human = nil then begin
        SysMsg('你的好友 ' + sParam + ' 不在线!!!', c_Red, t_Hint);
        Exit;
      end;
      if human = Self then begin
        SysMsg('你不能召唤自己!!!', c_Red, t_Hint);
        Exit;
      end;
      if human.m_boAllowGroupReCall then begin
        RecallHuman(human.m_sCharName, $1D);
        SendRefMsg(RM_510, 1, 0, $1D, 0, '');
        human.SendDelayMsg(Self, RM_510, 1, 0, $1D, 0, '', 100);
      end else begin
        SysMsg(human.m_sCharName + ' 不允许传送!!!', c_Red, t_Hint);
      end;
      Break;
    end;
  end;
end;

//调整元宝数量

procedure TPlayObject.CmdGameGold(Cmd: pTGameCmd; sHumanName: string; sCtr: string; nGold: Integer);
var
  PlayObject                            : TPlayObject;
  Ctr                                   : Char;
resourcestring
  sLogMsg                               = '[调整元宝] %s 给:%s %s %d 元宝';
begin
  Ctr := '1';
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCtr <> '') then begin
    Ctr := sCtr[1];
  end;

  if (sHumanName = '') or not (Ctr in ['=', '+', '-']) or (nGold < 0) or
    ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandGameGoldHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  case sCtr[1] of
    '=': begin
        if nGold > g_Config.nHumanMaxGameGold then begin
          SysMsg(sHumanGameGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        PlayObject.m_nGameGold := nGold;
      end;
    '+': begin
        if nGold + PlayObject.m_nGameGold > g_Config.nHumanMaxGameGold then begin
          SysMsg(sHumanGameGoldLargeThenLimit, c_Red, t_Hint);
          Exit;
        end;
        Inc(PlayObject.m_nGameGold, nGold);
      end;
    '-': begin
        nGold := _Max(0, PlayObject.m_nGameGold - nGold);
        PlayObject.m_nGameGold := nGold;
      end;
  end;
  if g_boGameLogGameGold then begin
    AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD,
      PlayObject.m_sMapName,
        PlayObject.m_nCurrX,
        PlayObject.m_nCurrY,
        PlayObject.m_sCharName,
        g_Config.sGameGoldName,
        nGold,
        sCtr[1],
        m_sCharName]));
  end;
  GameGoldChanged();
  PlayObject.SysMsg(Format(g_sGameCommandGameGoldHumanMsg,
    [g_Config.sGameGoldName, nGold, PlayObject.m_nGameGold,
    g_Config.sGameGoldName]), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandGameGoldGMMsg, [sHumanName,
    g_Config.sGameGoldName, nGold, PlayObject.m_nGameGold,
      g_Config.sGameGoldName]), c_Green, t_Hint);

  if g_Config.boShowMakeItemMsg and (m_btPermissionGM >= 6) then
    MainOutMessage(Format(sLogMsg, [m_sCharName, PlayObject.m_sCharName,
      sCtr[1], nGold]));
end;

procedure TPlayObject.CmdGamePoint(Cmd: pTGameCmd; sHumanName, sCtr: string;
  nPoint: Integer);
var
  PlayObject                            : TPlayObject;
  Ctr                                   : Char;
begin
  Ctr := '1';
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCtr <> '') then begin
    Ctr := sCtr[1];
  end;

  if (sHumanName = '') or not (Ctr in ['=', '+', '-']) or (nPoint < 0) or (nPoint
    > 100000000) or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandGamePointHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  case sCtr[1] of
    '=': begin
        PlayObject.m_nGamePoint := nPoint;
      end;
    '+': Inc(PlayObject.m_nGamePoint, nPoint);
    '-': Dec(PlayObject.m_nGamePoint, nPoint);
  end;
  if g_boGameLogGamePoint then begin
    AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEPOINT,
      PlayObject.m_sMapName,
        PlayObject.m_nCurrX,
        PlayObject.m_nCurrY,
        PlayObject.m_sCharName,
        g_Config.sGamePointName,
        nPoint,
        sCtr[1],
        m_sCharName]));
  end;
  GameGoldChanged();
  PlayObject.SysMsg(Format(g_sGameCommandGamePointHumanMsg, [nPoint,
    PlayObject.m_nGamePoint]), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandGamePointGMMsg, [sHumanName, nPoint,
    PlayObject.m_nGamePoint]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdGroupRecall(sCmd: string; AllRecall: Boolean = False);
var
  i                                     : Integer;
  dwValue                               : LongWord;
  PlayObject                            : TPlayObject;
begin
  if m_boRecallSuite or (m_btPermissionGM >= 6) then begin
    if not m_PEnvir.m_MapFlag.boNORECALL then begin
      dwValue := (GetTickCount - m_dwGroupRcallTick) div 1000;
      m_dwGroupRcallTick := m_dwGroupRcallTick + dwValue * 1000;
      if m_btPermissionGM >= 6 then m_wGroupRcallTime := 0;

      if m_wGroupRcallTime > dwValue then begin
        Dec(m_wGroupRcallTime, dwValue);
      end else m_wGroupRcallTime := 0;
      if m_wGroupRcallTime = 0 then begin
        if m_boArrow then begin
          SysMsg('您正在执行任务,目前无法使用此功能!!!',
            c_Red, t_Hint);
          Exit;
        end;

        if m_wShopItemCount > 0 then begin
          SysMsg('您正在摆摊,目前无法使用此功能!!!',
            c_Red, t_Hint);
          Exit;
        end;

        if m_GroupOwner = Self then begin
          for i := 1 to m_GroupMembers.Count - 1 do begin
            PlayObject := TPlayObject(m_GroupMembers.Objects[i]);
            if (PlayObject.m_boAllowGroupReCall = True) or (AllRecall = True) then begin
              if PlayObject.m_PEnvir.m_MapFlag.boNORECALL then begin
                SysMsg(Format('%s 所在的地图不允许传送。',
                  [PlayObject.m_sCharName]), c_Red, t_Hint);
              end else begin
                RecallHuman(PlayObject.m_sCharName, 0);
                //PlayObject.SendDelayMsg(self,RM_510,1,0,$20,0,'',100);
              end;
            end else begin
              SysMsg(Format('%s 不允许天地合一!!!',
                [PlayObject.m_sCharName]), c_Red, t_Hint);
            end;
          end;
          m_dwGroupRcallTick := GetTickCount();
          m_wGroupRcallTime := g_Config.nGroupRecallTime;
        end;
      end else begin
        SysMsg(Format('%d 秒之后才可以再使用此功能!!!',
          [m_wGroupRcallTime]), c_Red, t_Hint);
      end;
    end else begin
      SysMsg('此地图禁止使用此命令!!!', c_Red, t_Hint);
    end;
  end else begin
    SysMsg('您现在还无法使用此功能!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdGuildRecall(sCmd, sParam: string);
var
  i, ii                                 : Integer;
  dwValue                               : LongWord;
  PlayObject                            : TPlayObject;
  GuildRank                             : pTGuildRank;
  nRecallCount, nNoRecallCount          : Integer;
  Castle                                : TUserCastle;
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('命令功能: 行会传送,行会掌门人可以将整个行会成员全部集中。', c_Red, t_Hint);
    Exit;
  end;

  if not m_boGuildMove and (m_btPermissionGM < 6) then begin
    SysMsg('您现在还无法使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if not IsGuildMaster then begin
    SysMsg('行会掌门人才可以使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_PEnvir.m_MapFlag.boNOGUILDRECALL then begin
    SysMsg('本地图不允许使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  Castle := g_CastleManager.InCastleWarArea(Self);

  //if UserCastle.m_boUnderWar and UserCastle.InCastleWarArea(m_PEnvir,m_nCurrX,m_nCurrY) then begin
  if (Castle <> nil) and Castle.m_boUnderWar then begin
    SysMsg('攻城区域不允许使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  nRecallCount := 0;
  nNoRecallCount := 0;
  dwValue := (GetTickCount - m_dwGroupRcallTick) div 1000;
  m_dwGroupRcallTick := m_dwGroupRcallTick + dwValue * 1000;
  if m_btPermissionGM >= 6 then m_wGroupRcallTime := 0;
  if m_wGroupRcallTime > dwValue then begin
    Dec(m_wGroupRcallTime, dwValue);
  end else m_wGroupRcallTime := 0;

  if m_wGroupRcallTime > 0 then begin
    SysMsg(Format('%d 秒之后才可以再使用此功能!!!',
      [m_wGroupRcallTime]), c_Red, t_Hint);
    Exit;
  end;
  if m_boArrow then begin
    SysMsg('您正在执行任务,目前无法使用此功能!!!',
      c_Red, t_Hint);
    Exit;
  end;
  for i := 0 to TGuild(m_MyGuild).m_RankList.Count - 1 do begin
    GuildRank := TGuild(m_MyGuild).m_RankList.Items[i];
    for ii := 0 to GuildRank.MemberList.Count - 1 do begin
      PlayObject := TPlayObject(GuildRank.MemberList.GetValues(GuildRank.MemberList.Keys[ii]));
      if PlayObject <> nil then begin
        if PlayObject = Self then begin
          //          Inc(nNoRecallCount);
          Continue;
        end;
        if PlayObject.m_boAllowGuildReCall then begin
          if PlayObject.m_PEnvir.m_MapFlag.boNORECALL then begin
            SysMsg(Format('%s 所在的地图不允许传送。',
              [PlayObject.m_sCharName]), c_Red, t_Hint);
          end else begin
            RecallHuman(PlayObject.m_sCharName, $1C);
            PlayObject.SendDelayMsg(Self, RM_510, 1, 0, $1C, 0, '', 100);
            Inc(nRecallCount);
          end;
        end else begin
          Inc(nNoRecallCount);
          SysMsg(Format('%s 不允许行会合一!!!',
            [PlayObject.m_sCharName]), c_Red, t_Hint);
        end;
      end;
    end;
  end;
  //  SysMsg('已传送' + IntToStr(nRecallCount) + '个成员,' + IntToStr(nNoRecallCount) + '个成员未被传送。',c_Green,t_Hint);
  SysMsg(Format('已传送%d个成员,%d个成员未被传送。',
    [nRecallCount, nNoRecallCount]), c_Green, t_Hint);
  m_dwGroupRcallTick := GetTickCount();
  m_wGroupRcallTime := g_Config.nGuildRecallTime;
end;

procedure TPlayObject.CmdGuildWar(sCmd, sGuildName: string);                                        //004CE9F0
begin
  if (m_btPermissionGM < 6) then Exit;
end;

procedure TPlayObject.CmdHair(Cmd: pTGameCmd; sHumanName: string; nHair:
  Integer);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (nHair < 0) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 类型值', c_Red,
      t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    PlayObject.m_btHair := nHair;
    PlayObject.FeatureChanged();
    SysMsg(sHumanName + ' 的头发已改变。', c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdHumanCount(Cmd: pTGameCmd; sMapName: string);
var
  Envir                                 : TEnvirnoment;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMapName = '') or ((sMapName <> '') and (sMapName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandHumanCountHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  if sMapName = 'SELF' then
    Envir := m_PEnvir
  else
    Envir := g_MapManager.FindMap(sMapName);

  if Envir = nil then begin
    SysMsg(g_sGameCommandMobCountMapNotFound, c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandMobCountMonsterCount, [UserEngine.GetMapHuman(Envir)]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdHumanInfo(Cmd: pTGameCmd; sHumanName: string);
//004CFC98
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandInfoHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  SysMsg(PlayObject.GeTBaseObjectInfo(), c_Green, t_Hint);
end;

procedure TPlayObject.CmdHumanLocal(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandHumanLocalHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandHumanLocalMsg, [sHumanName, m_sIPLocal
    {GetIPLocal(PlayObject.m_sIPaddr)}]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdHunger(sCmd, sHumanName: string; nHungerPoint:
  Integer);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sHumanName = '') or (nHungerPoint < 0) then begin
    SysMsg('命令格式: @' + sCmd + ' 人物名称 能量值', c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    PlayObject.m_nHungerStatus := nHungerPoint;
    PlayObject.SendMsg(PlayObject, RM_MYSTATUS, 0, 0, 0, 0, '');
    PlayObject.RefMyStatus();
    SysMsg(sHumanName + ' 的能量值已改变。', c_Green, t_Hint);
  end else begin
    SysMsg(sHumanName + '没有在线!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdIncPkPoint(Cmd: pTGameCmd; sHumanName: string; nPoint:
  Integer);                                                                                         //004BF4D4
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandIncPkPointHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject.IncPkPoint(nPoint);
  PlayObject.RefNameColor();
  if nPoint > 0 then
    SysMsg(Format(g_sGameCommandIncPkPointAddPointMsg, [sHumanName, nPoint]),
      c_Green, t_Hint)
  else
    SysMsg(Format(g_sGameCommandIncPkPointDecPointMsg, [sHumanName, -nPoint]),
      c_Green, t_Hint);
end;

procedure TPlayObject.CmdKickHuman(Cmd: pTGameCmd; sHumName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumName = '') or ((sHumName <> '') and (sHumName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandKickHumanHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    PlayObject.m_boOfflineGetGamePoint := False;
    PlayObject.m_boKickFlag := True;
    PlayObject.m_boEmergencyClose := True;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdKill(Cmd: pTGameCmd; sHumanName: string);
var
  BaseObject                            : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumanName <> '' then begin
    BaseObject := UserEngine.GetPlayObject(sHumanName);
    if BaseObject = nil then begin
      SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red,
        t_Hint);
      Exit;
    end;
  end else begin
    BaseObject := GetPoseCreate();
    if BaseObject = nil then begin
      SysMsg('命令使用方法不正确,必须与角色面对面站好!!!', c_Red, t_Hint);
      Exit;
    end;
  end;
  BaseObject.m_WAbil.dwHP := 0;
  BaseObject.Die;
end;

procedure TPlayObject.CmdLockLogin(Cmd: pTGameCmd);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if not g_Config.boLockHumanLogin then begin
    SysMsg('本服务器还没有启用登录锁功能!!!', c_Red,
      t_Hint);
    Exit;
  end;

  if m_boLockLogon and not m_boLockLogoned then begin
    SysMsg('您还没有打开登录锁或还没有设置锁密码!!!',
      c_Red, t_Hint);
    Exit;
  end;

  m_boLockLogon := not m_boLockLogon;
  if m_boLockLogon then begin
    SysMsg('已开启登录锁', c_Green, t_Hint);
  end else begin
    SysMsg('已关闭登录锁', c_Green, t_Hint);
  end;

end;

procedure TPlayObject.CmdLotteryTicket(sCmd: string; nPermission: Integer;
  sParam1: string);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sParam1 = '') or ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandLotteryTicketMsg, [g_Config.nWinLotteryCount,
    g_Config.nNoWinLotteryCount,
      g_Config.nWinLotteryLevel1,
      g_Config.nWinLotteryLevel2,
      g_Config.nWinLotteryLevel3,
      g_Config.nWinLotteryLevel4,
      g_Config.nWinLotteryLevel5,
      g_Config.nWinLotteryLevel6]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdLuckPoint(sCmd: string; nPermission: Integer;
  sHumanName, sCtr, sPoint: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandLuckPointHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;

  if sCtr = '' then begin
    SysMsg(Format(g_sGameCommandLuckPointMsg, [sHumanName,
      PlayObject.m_nBodyLuckLevel, PlayObject.m_dBodyLuck, PlayObject.m_nLuck]), c_Green, t_Hint);
    Exit;
  end;

end;

//制造物品命令

procedure TPlayObject.CmdMakeItem(Cmd: pTGameCmd; sItemName: string; nCount:
  Integer);                                                                                         //004CCE34
var
  i, nMaxCount, nCurCount               : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  logStr                                : string;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sItemName = '') then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGamecommandMakeHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  if (nCount <= 0) then nCount := 1;
  StdItem := UserEngine.GetStdItem(sItemName);
  if (m_btPermissionGM < Cmd.nPerMissionMax) then begin
    if (StdItem <> nil) and CheckSPCode(StdItem.SPCode, SP_DISABLEMAKE) then begin
      SysMsg(g_sGamecommandMakeItemNameOrPerMissionNot, c_Red, t_Hint);
      Exit                                                                                          //物品控制-禁止制造
    end;
    if g_CastleManager.InCastleWarArea(Self) <> nil then begin
      SysMsg(g_sGamecommandMakeInCastleWarRange, c_Red, t_Hint);
      Exit;
    end;
    if not InSafeZone then begin
      SysMsg(g_sGamecommandMakeInSafeZoneRange, c_Red, t_Hint);
      Exit;
    end;
    nCount := 1;
  end;
  if StdItem = nil then Exit;

  if CheckSPCode(StdItem.Reserved, RE_ALLOWPILE) then begin
    nMaxCount := _MAX(1, StdItem.Stock);
    if m_ItemList.Count >= m_nBagSize then Exit;
    while nCount > 0 do begin
      nCurCount := _MIN(nCount, nMaxCount);
      Dec(nCount, nCurCount);
      New(UserItem);
      if UserEngine.CopyToUserItemFromName(sItemName, UserItem) then begin
        UserItem^.Dura := nCurCount;
        UserItem^.DuraMax := nMaxCount;
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if (StdItem.Price >= 15000) and not g_Config.boTestServer and
          (m_btPermissionGM < 5) then begin
          Dispose(UserItem);
          Exit;
        end else begin
          if (g_Config.boTimeBackServer) or (g_Config.boMagicCityServer) then begin
            if g_Config.EnableGoodItemTimeBack = True then
            begin
              if (Random(g_Config.nMakeRandomAddValueTimeBack0) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 0) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 20);
              end;
              if (Random(g_Config.nMakeRandomAddValueTimeBack1) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 1) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 30);
              end;
              if (Random(g_Config.nMakeRandomAddValueTimeBack2) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 2) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 31);
              end;
            end;
          end else begin
            if Random(g_Config.nMakeRandomAddValue {10}) = 0 then
              UserEngine.RandomUpgradeItem(UserItem);
          end;
        end;
        if StdItem.StdMode in [15, 19, 20, 21, 22, 23, 24, 26] then begin
          if StdItem.Shape in [130, 131, 132] then begin
            UserEngine.GetUnknowItemValue(UserItem);
          end;
        end;
        if m_btPermissionGM >= Cmd.nPerMissionMax then begin
          UserItem.MakeIndex := GetItemNumberEx();
          //制造的物品另行取得物品ID
        end;
        if IsEnoughBag then begin
          if AddItemToBag(UserItem) then begin
            SendAddItem(UserItem);
            if g_Config.boShowMakeItemMsg and (m_btPermissionGM >= 6) then begin
              logStr := '[制造物品] ' + m_sCharName + ' ' + sItemName + '(' + IntToStr(UserItem.MakeIndex) + ')';
              MainOutMessage(logStr);
              SysMsg(logStr, c_Red, t_Hint);
            end;
            if StdItem.boGameLog = 1 then
              AddGameDataLog('9' + #9 +
                m_sMapName + #9 +
                IntToStr(m_nCurrX) + #9 +
                IntToStr(m_nCurrY) + #9 +
                m_sCharName + #9 +
                sItemName + #9 +
                IntToStr(UserItem.MakeIndex) + #9 +
                IntToStr(nCurCount) + #9 +
                m_sCharName);
          end;
        end else begin
          Dispose(UserItem);
          Exit;
        end;
      end else begin
        Dispose(UserItem);
        SysMsg(Format(g_sGamecommandMakeItemNameNotFound, [sItemName]), c_Red, t_Hint);
        Exit;
      end;
    end;
  end else begin
    if (nCount > 10) then nCount := 10;
    for i := 0 to nCount - 1 do begin
      if m_ItemList.Count >= m_nBagSize then Exit;
      New(UserItem);
      if UserEngine.CopyToUserItemFromName(sItemName, UserItem) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if (StdItem.Price >= 15000) and not g_Config.boTestServer and
          (m_btPermissionGM < 5) then begin
          Dispose(UserItem);
          Exit;
        end else begin
          if (g_Config.boTimeBackServer) or (g_Config.boMagicCityServer) then begin
            if g_Config.EnableGoodItemTimeBack = True then
            begin
              if (Random(g_Config.nMakeRandomAddValueTimeBack0) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 0) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 20);
              end;
              if (Random(g_Config.nMakeRandomAddValueTimeBack1) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 1) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 30);
              end;
              if (Random(g_Config.nMakeRandomAddValueTimeBack2) = 0) and (g_Config.nMakeRandomAddValueTimeBack0 > 2) then begin
                UserEngine.RandomTimeBackUpgradeItem(UserItem, 31);
              end;
            end;
          end else begin
            if Random(g_Config.nMakeRandomAddValue {10}) = 0 then
              UserEngine.RandomUpgradeItem(UserItem);
          end;
        end;
        if StdItem.StdMode in [15, 19, 20, 21, 22, 23, 24, 26] then begin
          if StdItem.Shape in [130, 131, 132] then begin
            UserEngine.GetUnknowItemValue(UserItem);
          end;
        end;
        if m_btPermissionGM >= Cmd.nPerMissionMax then begin
          UserItem.MakeIndex := GetItemNumberEx();
          //制造的物品另行取得物品ID
        end;
        if AddItemToBag(UserItem) then begin
          SendAddItem(UserItem);
          if g_Config.boShowMakeItemMsg and (m_btPermissionGM >= 6) then begin
            logStr := '[制造物品] ' + m_sCharName + ' ' + sItemName + '(' + IntToStr(UserItem.MakeIndex) + ')';
            MainOutMessage(logStr);
            SysMsg(logStr, c_Red, t_Hint);
          end;

          if StdItem.boGameLog = 1 then
            AddGameDataLog('5' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              '0');
        end else begin
          Dispose(UserItem);
          Break;
        end;
      end else begin
        Dispose(UserItem);
        SysMsg(Format(g_sGamecommandMakeItemNameNotFound, [sItemName]), c_Red, t_Hint);
        Break;
      end;
    end;
  end;
end;

procedure TPlayObject.CmdMapMove(Cmd: pTGameCmd; sMapName: string);
var
  Envir                                 : TEnvirnoment;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMapName = '') or ((sMapName <> '') and (sMapName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, g_sGameCommandMoveHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  Envir := g_MapManager.FindMap(sMapName);
  if (Envir = nil) then begin
    SysMsg(Format(g_sTheMapNotFound, [sMapName]), c_Red, t_Hint);
    Exit;
  end;
  if (m_btPermissionGM >= Cmd.nPerMissionMax) or CanMoveMap(sMapName) then begin
    SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
    MapRandomMove(sMapName, 0, nil);
  end else begin
    SysMsg(Format(g_sTheMapDisableMove, [sMapName, Envir.m_sMapDesc]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdMapMoveHuman(Cmd: pTGameCmd; sSrcMap, sDenMap: string);
var
  SrcEnvir, DenEnvir                    : TEnvirnoment;
  HumanList                             : TList;
  i, nMapIndex                          : Integer;
  MoveHuman                             : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sDenMap = '') or (sSrcMap = '') or ((sSrcMap <> '') and (sSrcMap[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandMapMoveHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  SrcEnvir := g_MapManager.FindMap(sSrcMap);
  DenEnvir := g_MapManager.FindMap(sDenMap);
  if (SrcEnvir = nil) then begin
    SysMsg(Format(g_sGameCommandMapMoveMapNotFound, [sSrcMap]), c_Red, t_Hint);
    Exit;
  end;
  if (DenEnvir = nil) then begin
    SysMsg(Format(g_sGameCommandMapMoveMapNotFound, [sDenMap]), c_Red, t_Hint);
    Exit;
  end;

  HumanList := TList.Create;
  UserEngine.GetMapRageHuman(SrcEnvir, SrcEnvir.m_nWidth div 2,
    SrcEnvir.m_nHeight div 2, 1000, HumanList);
  nMapIndex := -1;
  for i := 0 to HumanList.Count - 1 do begin
    MoveHuman := TPlayObject(HumanList.Items[i]);
    if MoveHuman <> Self then
      MoveHuman.MapRandomMove(sDenMap, 0, @nMapIndex);
  end;
  HumanList.free;
end;

procedure TPlayObject.CmdMasterRecall(sCmd, sParam: string);
var
  i                                     : Integer;
  MasterHuman                           : TPlayObject;
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('命令格式: @' + sCmd +
      ' (师徒传送,师父可以将徒弟传送到自己身边,徒弟必须允许传送。)',
      c_Green, t_Hint);
    Exit;
  end;
  if not m_boMaster then begin
    SysMsg('只能师父才能使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_MasterList.Count = 0 then begin
    SysMsg('你的徒弟一个都不在线!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_PEnvir.m_MapFlag.boNOMASTERRECALL then begin
    SysMsg('本地图禁止师徒传送!!!', c_Red, t_Hint);
    Exit;
  end;
  if GetTickCount - m_dwMasterRecallTick < 10000 then begin
    SysMsg('稍等伙才能再次使用此功能!!!', c_Red, t_Hint);
    Exit;
  end;
  if m_boArrow then begin
    SysMsg('您正在执行任务,目前无法使用此功能!!!',
      c_Red, t_Hint);
    Exit;
  end;
  for i := 0 to m_MasterList.Count - 1 do begin
    MasterHuman := TPlayObject(m_MasterList.Items[i]);
    if MasterHuman.m_boCanMasterRecall and not MasterHuman.m_boGhost and not
      MasterHuman.m_boDeath then begin
      RecallHuman(MasterHuman.m_sCharName, $1F);
      MasterHuman.SendDelayMsg(Self, RM_510, 1, 0, $1F, 0, '', 100);
    end else begin
      SysMsg(MasterHuman.m_sCharName + ' 不允许传送!!!', c_Red,
        t_Hint);
    end;
  end;
  SendRefMsg(RM_510, 1, 0, $1F, 0, '');
end;

procedure TPlayObject.CmdMemberFunction(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('打开会员功能窗口.', c_Red, t_Hint);
    Exit;
  end;
  ExecuteScript(g_ManageNPC, '@Member');
end;

procedure TPlayObject.CmdMemberFunctionEx(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('打开会员功能窗口.', c_Red, t_Hint);
    Exit;
  end;
  ExecuteScript(g_FunctionNPC, '@Member');
end;

procedure TPlayObject.CmdMission(Cmd: pTGameCmd; sX, sY: string);                                   //004CCA08
var
  nX, nY                                : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sX = '') or (sY = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' X  Y', c_Red, t_Hint);
    Exit;
  end;
  nX := Str_ToInt(sX, 0);
  nY := Str_ToInt(sY, 0);
  g_boMission := True;
  g_sMissionMap := m_sMapName;
  g_nMissionX := nX;
  g_nMissionY := nY;
  SysMsg('怪物集中目标已设定为: ' + m_sMapName + '(' +
    IntToStr(g_nMissionX) + ':' + IntToStr(g_nMissionY) + ')', c_Green, t_Hint);
end;

procedure TPlayObject.CmdMob(Cmd: pTGameCmd; sMonName: string; nCount, nLevel:
  Integer; sShowName: string);                                                                      //004CC7F4
var
  i                                     : Integer;
  nX, nY                                : Integer;
  Monster                               : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMonName = '') or ((sMonName <> '') and (sMonName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandMobHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  if nCount <= 0 then nCount := 1;
  if not (nLevel in [0..10]) then nLevel := 0;

  nCount := _MIN(64, nCount);
  GetFrontPosition(nX, nY);
  for i := 0 to nCount - 1 do begin
    Monster := UserEngine.RegenMonsterByName(m_PEnvir, nX, nY,
      sMonName, sShowName);
    if Monster <> nil then begin
      Monster.m_wSlaveMakeLevel := nLevel;
      Monster.m_wSlaveExpLevel := nLevel;
      Monster.RecalcAbilitys;
      Monster.RefNameColor;
    end else begin
      SysMsg(g_sGameCommandMobMsg, c_Red, t_Hint);
      Break;
    end;
  end;
end;

procedure TPlayObject.CmdMobCount(Cmd: pTGameCmd; sMapName: string);
var
  Envir                                 : TEnvirnoment;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMapName = '') or ((sMapName <> '') and (sMapName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandMobCountHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  Envir := g_MapManager.FindMap(sMapName);
  if Envir = nil then begin
    SysMsg(g_sGameCommandMobCountMapNotFound, c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandMobCountMonsterCount,
    [UserEngine.GetMapMonster(Envir, nil)]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdMobFireBurn(Cmd: pTGameCmd; sMAP, sX, sY, sType,
  sTime, sPoint: string);
var
  nX, nY, nType, nTime, nPoint          : Integer;
  FireBurnEvent                         : TFireBurnEvent;
  Envir                                 : TEnvirnoment;
  OldEnvir                              : TEnvirnoment;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMAP = '') or ((sMAP <> '') and (sMAP[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandMobFireBurnHelpMsg, [Cmd.sCmd, sMAP, sX, sY,
      sType, sTime, sPoint]), c_Red, t_Hint);
    Exit;
  end;

  if (CompareText(sMAP, 'SELF') = 0) or (CompareText(sMAP, 'HERE') = 0) then begin
    sMAP := m_PEnvir.m_sMapName;
    nX := m_nCurrX + Str_ToInt(sX, -1);
    nY := m_nCurrY + Str_ToInt(sY, -1);
  end else begin
    nX := Str_ToInt(sX, -1);
    nY := Str_ToInt(sY, -1);
  end;

  nType := Str_ToInt(sType, -1);
  nTime := Str_ToInt(sTime, -1);
  nPoint := Str_ToInt(sPoint, -1);
  if nPoint < 0 then nPoint := 1;

  if (sMAP = '') or (nX < 0) or (nY < 0) or (nType < 0) or (nTime < 0) or (nPoint < 0) then begin
    SysMsg(Format(g_sGameCommandMobFireBurnHelpMsg, [Cmd.sCmd, sMAP, sX, sY,
      sType, sTime, sPoint]), c_Red, t_Hint);
    Exit;
  end;
  Envir := g_MapManager.FindMap(sMAP);
  if Envir <> nil then begin
    OldEnvir := m_PEnvir;
    m_PEnvir := Envir;
    FireBurnEvent := TFireBurnEvent.Create(Self, nX, nY, nType, nTime * 1000, nPoint);
    g_EventManager.AddEvent(FireBurnEvent);
    m_PEnvir := OldEnvir;
    Exit;
  end;
  SysMsg(Format(g_sGameCommandMobFireBurnMapNotFountMsg, [Cmd.sCmd, sMAP]), c_Red, t_Hint);
end;

procedure TPlayObject.CmdMobLevel(Cmd: pTGameCmd; Param: string);                                   //004CFD5C
var
  i                                     : Integer;
  BaseObjectList                        : TList;
  BaseObject                            : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((Param <> '') and (Param[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;

  BaseObjectList := TList.Create;
  m_PEnvir.GetRangeBaseObject(m_nCurrX, m_nCurrY, 2, True, BaseObjectList);
  for i := 0 to BaseObjectList.Count - 1 do begin
    BaseObject := TBaseObject(BaseObjectList.Items[i]);
    SysMsg(BaseObject.GeTBaseObjectInfo(), c_Green, t_Hint);
  end;
  BaseObjectList.free;
end;

procedure TPlayObject.CmdMobNpc(sCmd: string; nPermission: Integer; sParam1,
  sParam2, sParam3, sParam4: string);
var
  nAppr                                 : Integer;
  boIsCastle                            : Boolean;
  Merchant                              : TMerchant;
  nX, nY                                : Integer;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sParam1 = '') or (sParam2 = '') or ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandMobNpcHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  nAppr := Str_ToInt(sParam3, 0);
  boIsCastle := (Str_ToInt(sParam4, 0) = 1);
  if sParam1 = '' then begin
    SysMsg('命令格式: @' + sCmd +
      ' NPC名称 脚本文件名 外形(数字) 属沙城(0,1)', c_Red, t_Hint);
    Exit;
  end;
  Merchant := TMerchant.Create;
  Merchant.m_sCharName := sParam1;
  Merchant.m_sMapName := m_sMapName;
  Merchant.m_PEnvir := m_PEnvir;
  Merchant.m_wAppr := nAppr;
  Merchant.m_nFlag := 0;
  Merchant.m_boCastle := boIsCastle;
  Merchant.m_sScript := sParam2;
  GetFrontPosition(nX, nY);
  Merchant.m_nCurrX := nX;
  Merchant.m_nCurrY := nY;
  Merchant.Initialize();
  UserEngine.AddMerchant(Merchant);
end;

procedure TPlayObject.CmdMobPlace(Cmd: pTGameCmd; sX, sY, sMonName, sCount:
  string);                                                                                          //004CCBB4
var
  i                                     : Integer;
  nCount, nX, nY                        : Integer;
  MEnvir                                : TEnvirnoment;
  mon                                   : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  nCount := _MIN(500, Str_ToInt(sCount, 0));
  nX := Str_ToInt(sX, 0);
  nY := Str_ToInt(sY, 0);
  MEnvir := g_MapManager.FindMap(g_sMissionMap);
  if (nX <= 0) or (nY <= 0) or (sMonName = '') or (nCount <= 0) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' X  Y 怪物名称 怪物数量',
      c_Red, t_Hint);
    Exit;
  end;
  if not g_boMission or (MEnvir = nil) then begin
    SysMsg('还没有设定怪物集中点!!!', c_Red, t_Hint);
    SysMsg('请先用命令' + g_GameCommand.Mission.sCmd +
      '设置怪物的集中点。', c_Red, t_Hint);
    Exit;
  end;

  if (MEnvir.m_MapFlag.boCanMirror) then begin
    SysMsg('目标不能为镜像地图!!!', c_Red, t_Hint);
    Exit;
  end;

  for i := 0 to nCount - 1 do begin
    mon := UserEngine.RegenMonsterByName(MEnvir, nX, nY, sMonName);
    if mon <> nil then begin
      mon.m_boMission := True;
      mon.m_nMissionX := g_nMissionX;
      mon.m_nMissionY := g_nMissionY;
    end else Break;
  end;
  SysMsg(IntToStr(nCount) + ' 只 ' + sMonName + ' 已正在往地图 ' +
    g_sMissionMap + ' ' + IntToStr(g_nMissionX) + ':' + IntToStr(g_nMissionY) +
    ' 集中。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdNpcScript(sCmd: string; nPermission: Integer; sParam1,
  sParam2, sParam3: string);
var
  BaseObject                            : TBaseObject;
  nNPCType                              : Integer;
  i                                     : Integer;
  sScriptFileName                       : string;
  Merchant                              : TMerchant;
  NormNpc                               : TNormNpc;
  LoadList                              : TStringList;
  sScriptLine                           : string;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sParam1 <> '') or ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandNpcScriptHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  nNPCType := -1;
  BaseObject := GetPoseCreate();
  if BaseObject <> nil then begin
    for i := 0 to UserEngine.m_MerchantList.Count - 1 do begin
      if TBaseObject(UserEngine.m_MerchantList.Items[i]) = BaseObject then begin
        nNPCType := 0;
        Break;
      end;
    end;
    for i := 0 to UserEngine.QuestNPCList.Count - 1 do begin
      if TBaseObject(UserEngine.QuestNPCList.Items[i]) = BaseObject then begin
        nNPCType := 1;
        Break;
      end;
    end;
  end;
  if nNPCType < 0 then begin
    SysMsg('命令使用方法不正确,必须与NPC面对面,才能使用此命令!!!', c_Red, t_Hint);
    Exit;
  end;

  if sParam1 = '' then begin
    if nNPCType = 0 then begin
      Merchant := TMerchant(BaseObject);
      sScriptFileName := g_Config.sEnvirDir + sMarket_Def + Merchant.m_sScript +
        '-' + Merchant.m_sMapName + '.txt';
    end;
    if nNPCType = 1 then begin
      NormNpc := TNormNpc(BaseObject);
      sScriptFileName := g_Config.sEnvirDir + sNpc_def + NormNpc.m_sCharName +
        '-' + NormNpc.m_sMapName + '.txt';
    end;
    if FileExists(sScriptFileName) then begin
      LoadList := TStringList.Create;
      try
        LoadList.LoadFromFile(sScriptFileName);
      except
        SysMsg('读取脚本文件错误: ' + sScriptFileName, c_Red, t_Hint);
      end;
      for i := 0 to LoadList.Count - 1 do begin
        sScriptLine := Trim(LoadList.Strings[i]);
        sScriptLine := ReplaceChar(sScriptLine, ' ', ',');
        SysMsg(IntToStr(i) + ',' + sScriptLine, c_Blue, t_Hint);
      end;
      LoadList.free;
    end;
  end;
end;

procedure TPlayObject.CmdOPDeleteSkill(sHumanName, sSkillName: string);
//004CE938
begin
  if (m_btPermissionGM < 6) then Exit;
end;

procedure TPlayObject.CmdOPTraining(sHumanName, sSkillName: string;
  nLevel: Integer);                                                                                 //004CC468
begin
  if (m_btPermissionGM < 6) then Exit;
end;

procedure TPlayObject.CmdPKpoint(Cmd: pTGameCmd; sHumanName: string);                               //004CC61C
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandPKPointHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandPKPointMsg, [sHumanName, PlayObject.m_nPkPoint]),
    c_Green, t_Hint);
end;

//004CDA38

procedure TPlayObject.CmdPositionMove(Cmd: pTGameCmd; sMapName, sX, sY: string);
var
  Envir                                 : TEnvirnoment;
  nX, nY                                : Integer;
begin
  try
    if (m_btPermissionGM < Cmd.nPermissionMin) then begin
      SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
      Exit;
    end;
    if (sMapName = '') or (sX = '') or (sY = '') or ((sMapName <> '') and
      (sMapName[1] = '?')) then begin
      SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
        g_sGameCommandPositionMoveHelpMsg]), c_Red, t_Hint);
      Exit;
    end;
    if (m_btPermissionGM >= Cmd.nPerMissionMax) or CanMoveMap(sMapName) then begin
      Envir := g_MapManager.FindMap(sMapName);
      if Envir <> nil then begin
        nX := Str_ToInt(sX, 0);
        nY := Str_ToInt(sY, 0);
        if Envir.CanWalk(nX, nY, True) then begin
          SpaceMove(sMapName, nX, nY, 0, nil);
        end else begin
          SysMsg(Format(g_sGameCommandPositionMoveCanotMoveToMap, [sMapName, sX,
            sY]), c_Green, t_Hint);
        end;
      end;
    end else begin
      SysMsg(Format(g_sTheMapDisableMove, [sMapName, Envir.m_sMapDesc]), c_Red,
        t_Hint);
    end;
  except
    on E: Exception do begin
      MainOutMessage('[Exceptioin] TPlayObject.CmdPositionMove');
      MainOutMessage(E.Message);
    end;

  end;
end;

procedure TPlayObject.CmdPrvMsg(sCmd: string; nPermission: Integer;
  sHumanName: string);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandPrvMsgHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  for i := m_BlockWhisperList.Count - 1 downto 0 do begin
    if CompareText(m_BlockWhisperList.Strings[i], sHumanName) = 0 then begin
      m_BlockWhisperList.Delete(i);
      SysMsg(Format(g_sGameCommandPrvMsgUnLimitMsg, [sHumanName]), c_Green,
        t_Hint);
      Exit;
    end;
  end;
  m_BlockWhisperList.Add(sHumanName);
  SysMsg(Format(g_sGameCommandPrvMsgLimitMsg, [sHumanName]), c_Green, t_Hint);

end;

procedure TPlayObject.CmdReAlive(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandReAliveHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject.ReAlive;
  PlayObject.m_WAbil.dwHP := PlayObject.m_WAbil.dwMaxHP;
  PlayObject.RecalcAbilitys();
  PlayObject.SendMsg(PlayObject, RM_ABILITY, 0, 0, 0, 0, '');
  SysMsg(Format(g_sGameCommandReAliveMsg, [sHumanName]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdRecallHuman(Cmd: pTGameCmd; sHumanName: string);
//004CE250
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandRecallHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  RecallHuman(sHumanName, 0);
end;

procedure TPlayObject.CmdRecallMob(Cmd: pTGameCmd; sMonName: string; nCount,
  nLevel, nAutoChangeColor, nFixColor: Integer);                                                    //004CC8C4
var
  i                                     : Integer;
  N10, n14                              : Integer;
  mon                                   : TBaseObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sMonName = '') or ((sMonName <> '') and (sMonName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandRecallMobHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  if nLevel >= 10 then nLevel := 0;
  if nCount <= 0 then nCount := 1;
  for i := 0 to nCount - 1 do begin
    if m_SlaveList.Count >= 20 then Break;
    GetFrontPosition(N10, n14);
    mon := UserEngine.RegenMonsterByName(m_PEnvir, N10, n14, sMonName);
    if mon <> nil then begin
      mon.m_wSlaveMakeLevel := 3;
      mon.m_wSlaveExpLevel := nLevel;
      mon.m_Master := Self;
      mon.m_dwMasterRoyaltyTick := GetTickCount + 24 * 60 * 60 * 1000;
      if nAutoChangeColor = 1 then begin
        mon.m_boAutoChangeColor := True;
      end else
        if nFixColor > 0 then begin
          mon.m_boFixColor := True;
          mon.m_nFixColorIdx := nFixColor - 1;
        end;
      mon.RecalcAbilitys();
      mon.RefNameColor();
      m_SlaveList.Add(mon);
    end;
  end;
end;

procedure TPlayObject.CmdReconnection(sCmd, sIPaddr, sPort: string);
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sIPaddr <> '') and (sIPaddr[1] = '?') then begin
    SysMsg('此命令用于改变客户端连接网关的IP及端口。',
      c_Blue, t_Hint);
    Exit;
  end;

  if (sIPaddr = '') or (sPort = '') then begin
    SysMsg('命令格式: @' + sCmd + ' IP地址 端口', c_Red, t_Hint);
    Exit;
  end;
  if (sIPaddr <> '') and (sPort <> '') then begin
    SendMsg(Self, RM_RECONNECTION, 0, 0, 0, 0, sIPaddr + '/' + sPort);
  end;
end;

procedure TPlayObject.CmdRefineWeapon(Cmd: pTGameCmd; nDc, nMc, nSc, nHit:
  Integer);                                                                                         //004CD1C4
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (nDc + nMc + nSc) > 10 then Exit;
  if m_UseItems[U_WEAPON].wIndex <= 0 then Exit;
  m_UseItems[U_WEAPON].btValue[0] := nDc;
  m_UseItems[U_WEAPON].btValue[1] := nMc;
  m_UseItems[U_WEAPON].btValue[2] := nSc;
  m_UseItems[U_WEAPON].btValue[5] := nHit;
  SendUpdateItem(@m_UseItems[U_WEAPON]);
  RecalcAbilitys();
  SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  MainOutMessage('[武器调整]' + m_sCharName + ' DC:' + IntToStr(nDc) + ' MC'
    + IntToStr(nMc) + ' SC' + IntToStr(nSc) + ' HIT:' + IntToStr(nHit));
end;

procedure TPlayObject.CmdReGotoHuman(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
  nMapIndex                             : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandReGotoHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  nMapIndex := PlayObject.m_PEnvir.Index;
  SpaceMove(PlayObject.m_PEnvir.m_sMapName, PlayObject.m_nCurrX,
    PlayObject.m_nCurrY, 0, @nMapIndex);

end;

procedure TPlayObject.CmdReloadAbuse(sCmd: string; nPermission: Integer;
  sParam1: string);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
end;

procedure TPlayObject.CmdReLoadAdmin(sCmd: string);
begin
  if (m_btPermissionGM < 6) then Exit;
  FrmDB.LoadAdminList();
  UserEngine.SendServerGroupMsg(213, g_Config.nServerNumber, '');
  SysMsg('管理员列表重新加载成功...', c_Green, t_Hint);
end;

procedure TPlayObject.CmdReloadGuild(sCmd: string; nPermission: Integer;
  sParam1: string);
var
  Guild                                 : TGuild;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sParam1 = '') or ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandReloadGuildHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  if g_Config.nServerNumber <> 0 then begin
    SysMsg(g_sGameCommandReloadGuildOnMasterserver, c_Red, t_Hint);
    Exit;
  end;

  Guild := g_GuildManager.FindGuild(sParam1);
  if Guild = nil then begin
    SysMsg(Format(g_sGameCommandReloadGuildNotFoundGuildMsg, [sParam1]), c_Red,
      t_Hint);
    Exit;
  end;
  //  Guild.LoadGuild();
  //  SysMsg(Format(g_sGameCommandReloadGuildSuccessMsg, [sParam1]), c_Red, t_Hint);
  //  UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, sParam1);
end;

procedure TPlayObject.CmdReloadGuildAll;                                                            //004CE530
begin
  if (m_btPermissionGM < 6) then Exit;
end;

procedure TPlayObject.CmdReloadLineNotice(sCmd: string;
  nPermission: Integer; sParam1: string);
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  if LoadLineNotice(g_Config.sNoticeDir + 'LineNotice.txt') then begin
    SysMsg(g_sGameCommandReloadLineNoticeSuccessMsg, c_Green, t_Hint);
  end else begin
    SysMsg(g_sGameCommandReloadLineNoticeFailMsg, c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdReloadManage(Cmd: pTGameCmd; sParam: string);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam <> '') and (sParam[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  if sParam = '' then begin
    if g_ManageNPC <> nil then begin
      g_ManageNPC.ClearScript();
      g_ManageNPC.LoadNPCScript();
      SysMsg('重新加载登录脚本完成...', c_Green, t_Hint);
    end else begin
      SysMsg('重新加载登录脚本失败...', c_Green, t_Hint);
    end;
  end else begin
    if g_FunctionNPC <> nil then begin
      g_FunctionNPC.ClearScript();
      g_FunctionNPC.LoadNPCScript();
      SysMsg('重新加载功能脚本完成...', c_Green, t_Hint);
    end else begin
      SysMsg('重新加载功能脚本失败...', c_Green, t_Hint);
    end;
    if g_WolShopNPC <> nil then begin
      g_WolShopNPC.ClearScript();
      g_WolShopNPC.LoadNPCScript();
      SysMsg('重新加载商城脚本完成...', c_Green, t_Hint);
    end else begin
      SysMsg('重新加载商城脚本失败...', c_Green, t_Hint);
    end;
  end;
end;

procedure TPlayObject.CmdReloadMonItems;                                                            //
//var
//  i                                : Integer;
//  Monster                          : pTMonInfo;
begin
  if (m_btPermissionGM < 6) then Exit;
  SysMsg('该命令已经取消,请使用重新加载怪物数据库命令...', c_Green, t_Hint);
  //  EnterCriticalSection(ProcessHumanCriticalSection);
  //  try
  //    for i := 0 to UserEngine.MonsterList.Count - 1 do begin
  //      Monster := pTMonInfo(UserEngine.MonsterList.Values[UserEngine.MonsterList.Keys[i]]);
        //FrmDB.LoadMonitems(UserEngine.MonsterList.Keys[i], Monster.ItemList);
  //    end;
  //    SysMsg('怪物爆物品列表重加载完成...', c_Green, t_Hint);
  //  finally
  //    LeaveCriticalSection(ProcessHumanCriticalSection);
  //  end;
end;

procedure TPlayObject.CmdReloadNpc(sParam: string);                                                 //004CFFF8
var
  i                                     : Integer;
  tmpList                               : TList;
  Merchant                              : TMerchant;
  NPC                                   : TNormNpc;
begin
  if (m_btPermissionGM < 6) then Exit;
  if CompareText('all', sParam) = 0 then begin
    FrmDB.ReLoadMerchants();
    UserEngine.ReloadMerchantList();
    SysMsg('交易NPC重新加载完成!!!', c_Red, t_Hint);
    UserEngine.ReloadNpcList();
    SysMsg('管理NPC重新加载完成!!!', c_Red, t_Hint);
    Exit;
  end;                                                                                              //004D0136
  tmpList := TList.Create;
  if UserEngine.GetMerchantList(m_PEnvir, m_nCurrX, m_nCurrY, 9, tmpList) > 0 then begin
    for i := 0 to tmpList.Count - 1 do begin
      Merchant := TMerchant(tmpList.Items[i]);
      Merchant.ClearScript;
      Merchant.LoadNPCScript;
      SysMsg(Merchant.m_sCharName + '重新加载成功...', c_Green, t_Hint);
    end;                                                                                            // for
  end else begin
    SysMsg('附近未发现任何交易NPC!!!', c_Red, t_Hint);
  end;
  tmpList.Clear;
  if UserEngine.GetNpcList(m_PEnvir, m_nCurrX, m_nCurrY, 9, tmpList) > 0 then begin
    for i := 0 to tmpList.Count - 1 do begin
      NPC := TNormNpc(tmpList.Items[i]);
      NPC.ClearScript;
      NPC.LoadNPCScript;
      SysMsg(NPC.m_sCharName + '重新加载成功...', c_Green, t_Hint);
    end;                                                                                            // for
  end else begin
    SysMsg('附近未发现任何管理NPC!!!', c_Red, t_Hint);
  end;
  tmpList.free;
end;

procedure TPlayObject.CmdReloadRobot;
begin
  RobotManage.RELOADROBOT();
  SysMsg('重新加载机器人配置完成...', c_Green, t_Hint);
end;

procedure TPlayObject.CmdReloadRobotManage;
begin
  if (m_btPermissionGM < 6) then Exit;
  if g_RobotNPC <> nil then begin
    g_RobotNPC.ClearScript();
    g_RobotNPC.LoadNPCScript();
    SysMsg('重新加载机器人专用脚本完成...', c_Green, t_Hint);
  end else begin
    SysMsg('重新加载机器人专用脚本失败...', c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdReNewLevel(Cmd: pTGameCmd; sHumanName, sLevel: string);
var
  PlayObject                            : TPlayObject;
  nLevel                                : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg('命令格式: @' + Cmd.sCmd +
      ' 人物名称 点数(为空则查看)', c_Red, t_Hint);
    Exit;
  end;
  nLevel := Str_ToInt(sLevel, -1);
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    if (nLevel >= 0) and (nLevel <= 255) then begin
      PlayObject.m_btReLevel := nLevel;
      PlayObject.RefShowName();
    end;
    SysMsg(sHumanName + ' 的转生等级为 ' +
      IntToStr(PlayObject.m_btReLevel), c_Green, t_Hint);
  end else begin
    SysMsg(sHumanName + ' 没在线上!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdRestBonuPoint(Cmd: pTGameCmd; sHumName: string);
var
  PlayObject                            : TPlayObject;
  nTotleUsePoint                        : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if sHumName = '' then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称', c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    nTotleUsePoint := PlayObject.m_BonusAbil.DC +
      PlayObject.m_BonusAbil.MC +
      PlayObject.m_BonusAbil.SC +
      PlayObject.m_BonusAbil.AC +
      PlayObject.m_BonusAbil.MAC +
      PlayObject.m_BonusAbil.HP +
      PlayObject.m_BonusAbil.MP +
      PlayObject.m_BonusAbil.Hit +
      PlayObject.m_BonusAbil.Speed +
      PlayObject.m_BonusAbil.X2;
    FillChar(PlayObject.m_BonusAbil, SizeOf(TNakedAbility), #0);

    Inc(PlayObject.m_nBonusPoint, nTotleUsePoint);
    PlayObject.SendMsg(PlayObject, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
    PlayObject.HasLevelUp(0);
    PlayObject.SysMsg('分配点数已复位!!!', c_Red, t_Hint);
    SysMsg(sHumName + ' 的分配点数已复位.', c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdSbkDoorControl(sCmd, sParam: string);
begin

end;

procedure TPlayObject.CmdSearchDear(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('此命令用于查询配偶当前所在位置。', c_Red, t_Hint);
    Exit;
  end;
  if m_sDearName = '' then begin
    SysMsg(g_sYouAreNotMarryedMsg {'你都没结婚查什么?'}, c_Red,
      t_Hint);
    Exit;
  end;
  if m_DearHuman = nil then begin
    if m_btGender = 0 then begin
      SysMsg(g_sYourWifeNotOnlineMsg {'你的老婆还没有上线!!!'},
        c_Red, t_Hint);
    end else begin
      SysMsg(g_sYourHusbandNotOnlineMsg
        {'你的老公还没有上线!!!'}, c_Red, t_Hint);
    end;
    Exit;
  end;

  if m_btGender = 0 then begin
    SysMsg(g_sYourWifeNowLocateMsg {'你的老婆现在位于:'}, c_Green,
      t_Hint);
    SysMsg(m_DearHuman.m_sCharName + ' ' + m_DearHuman.m_PEnvir.m_sMapDesc + '(' +
      IntToStr(m_DearHuman.m_nCurrX) + ':' + IntToStr(m_DearHuman.m_nCurrY) + ')',
      c_Green, t_Hint);
    m_DearHuman.SysMsg(g_sYourHusbandSearchLocateMsg
      {'你的老公正在找你,他现在位于:'}, c_Green, t_Hint);
    m_DearHuman.SysMsg(m_sCharName + ' ' + m_PEnvir.m_sMapDesc + '(' +
      IntToStr(m_nCurrX) + ':' + IntToStr(m_nCurrY) + ')', c_Green, t_Hint);
  end else begin
    SysMsg(g_sYourHusbandNowLocateMsg {'你的老公现在位于:'}, c_Red,
      t_Hint);
    SysMsg(m_DearHuman.m_sCharName + ' ' + m_DearHuman.m_PEnvir.m_sMapDesc + '(' +
      IntToStr(m_DearHuman.m_nCurrX) + ':' + IntToStr(m_DearHuman.m_nCurrY) + ')',
      c_Green, t_Hint);
    m_DearHuman.SysMsg(g_sYourWifeSearchLocateMsg
      {'你的老婆正在找你,她现在位于:'}, c_Green, t_Hint);
    m_DearHuman.SysMsg(m_sCharName + ' ' + m_PEnvir.m_sMapDesc + '(' +
      IntToStr(m_nCurrX) + ':' + IntToStr(m_nCurrY) + ')', c_Green, t_Hint);
  end;

end;

procedure TPlayObject.CmdSearchHuman(sCmd, sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if m_boProbeNecklace or (m_btPermissionGM >= 6) then begin
    if (sHumanName = '') then begin
      SysMsg('命令格式: @' + sCmd + ' 人物名称', c_Red, t_Hint);
      Exit;
    end;
    if ((GetTickCount - m_dwProbeTick) > 10000) or (m_btPermissionGM >= 3) then begin
      m_dwProbeTick := GetTickCount();
      PlayObject := UserEngine.GetPlayObject(sHumanName);
      if PlayObject <> nil then begin
        SysMsg(sHumanName + ' 现在位于 ' + PlayObject.m_PEnvir.m_sMapDesc + ' '
          + IntToStr(PlayObject.m_nCurrX) + ':' + IntToStr(PlayObject.m_nCurrY),
          c_Blue, t_Hint);
      end else begin
        SysMsg(sHumanName +
          ' 现在不在线,或位于其它服务器上!!!', c_Red,
          t_Hint);
      end;
    end else begin
      SysMsg(IntToStr((GetTickCount - m_dwProbeTick) div 1000 - 10) +
        ' 秒之后才可以再使用此功能!!!', c_Red, t_Hint);
    end;
  end else begin
    SysMsg('您现在还无法使用此功能!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdSearchMaster(sCmd, sParam: string);
var
  i                                     : Integer;
  human                                 : TPlayObject;
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('此命令用于查询师徒当前所在位置。', c_Red, t_Hint);
    Exit;
  end;
  if m_sMasterName[1] = '' then begin
    SysMsg(g_sYouAreNotMasterMsg, c_Red, t_Hint);
    Exit;
  end;
  if m_boMaster then begin
    if m_MasterList.Count <= 0 then begin
      SysMsg(g_sYourMasterListNotOnlineMsg, c_Red, t_Hint);
      Exit;
    end;
    SysMsg(g_sYourMasterListNowLocateMsg, c_Green, t_Hint);
    for i := 0 to m_MasterList.Count - 1 do begin
      human := TPlayObject(m_MasterList.Items[i]);
      SysMsg(human.m_sCharName + ' ' + human.m_PEnvir.m_sMapDesc + '(' +
        IntToStr(human.m_nCurrX) + ':' + IntToStr(human.m_nCurrY) + ')', c_Green,
        t_Hint);
      human.SysMsg(g_sYourMasterSearchLocateMsg, c_Green, t_Hint);
      human.SysMsg(m_sCharName + ' ' + m_PEnvir.m_sMapDesc + '(' +
        IntToStr(m_nCurrX) + ':' + IntToStr(m_nCurrY) + ')', c_Green, t_Hint);
    end;
  end else begin
    if m_MasterHuman = nil then begin
      SysMsg(g_sYourMasterNotOnlineMsg, c_Red, t_Hint);
      Exit;
    end;
    SysMsg(g_sYourMasterNowLocateMsg, c_Red, t_Hint);
    SysMsg(m_MasterHuman.m_sCharName + ' ' + m_MasterHuman.m_PEnvir.m_sMapDesc +
      '(' + IntToStr(m_MasterHuman.m_nCurrX) + ':' +
      IntToStr(m_MasterHuman.m_nCurrY) + ')', c_Green, t_Hint);
    m_MasterHuman.SysMsg(g_sYourMasterListSearchLocateMsg, c_Green, t_Hint);
    m_MasterHuman.SysMsg(m_sCharName + ' ' + m_PEnvir.m_sMapDesc + '(' +
      IntToStr(m_nCurrX) + ':' + IntToStr(m_nCurrY) + ')', c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdSetMapMode(sCmd, sMapName, sMapMode, sParam1,
  sParam2: string);
var
  Envir                                 : TEnvirnoment;
  sMsg                                  : string;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sMapName = '') or (sMapMode = '') then begin
    SysMsg('命令格式: @' + sCmd + ' 地图号 模式', c_Red, t_Hint);
    Exit;
  end;
  Envir := g_MapManager.FindMap(sMapName);
  if (Envir = nil) then begin
    SysMsg(sMapName + ' 不存在!!!', c_Red, t_Hint);
    Exit;
  end;
  if CompareText(sMapMode, 'SAFE') = 0 then begin
    if (sParam1 <> '') then begin
      Envir.m_MapFlag.boSAFE := True;
    end else begin
      Envir.m_MapFlag.boSAFE := False;
    end;
  end else
    if CompareText(sMapMode, 'DARK') = 0 then begin
      if (sParam1 <> '') then begin
        Envir.m_MapFlag.boDARK := True;
      end else begin
        Envir.m_MapFlag.boDARK := False;
      end;
    end else
      if CompareText(sMapMode, 'DARK') = 0 then begin
        if (sParam1 <> '') then begin
          Envir.m_MapFlag.boDARK := True;
        end else begin
          Envir.m_MapFlag.boDARK := False;
        end;
      end else
        if CompareText(sMapMode, 'FIGHT') = 0 then begin
          if (sParam1 <> '') then begin
            Envir.m_MapFlag.boFight := True;
          end else begin
            Envir.m_MapFlag.boFight := False;
          end;
        end else
          if CompareText(sMapMode, 'FIGHT3') = 0 then begin
            if (sParam1 <> '') then begin
              Envir.m_MapFlag.boFight3 := True;
            end else begin
              Envir.m_MapFlag.boFight3 := False;
            end;
          end else
            if CompareText(sMapMode, 'DAY') = 0 then begin
              if (sParam1 <> '') then begin
                Envir.m_MapFlag.boDAY := True;
              end else begin
                Envir.m_MapFlag.boDAY := False;
              end;
            end else
              if CompareText(sMapMode, 'QUIZ') = 0 then begin
                if (sParam1 <> '') then begin
                  Envir.m_MapFlag.boQUIZ := True;
                end else begin
                  Envir.m_MapFlag.boQUIZ := False;
                end;
              end else
                if CompareText(sMapMode, 'NORECONNECT') = 0 then begin
                  if (sParam1 <> '') then begin
                    Envir.m_MapFlag.boNORECONNECT := True;
                    Envir.m_MapFlag.sReConnectMap := sParam1;
                  end else begin
                    Envir.m_MapFlag.boNORECONNECT := False;
                  end;
                end else
                  if CompareText(sMapMode, 'MUSIC') = 0 then begin
                    if (sParam1 <> '') then begin
                      Envir.m_MapFlag.boMUSIC := True;
                      Envir.m_MapFlag.nMUSICID := Str_ToInt(sParam1, -1);
                    end else begin
                      Envir.m_MapFlag.boMUSIC := False;
                    end;
                  end else
                    if CompareText(sMapMode, 'EXPRATE') = 0 then begin
                      if (sParam1 <> '') then begin
                        Envir.m_MapFlag.boEXPRATE := True;
                        Envir.m_MapFlag.nEXPRATE := Str_ToInt(sParam1, -1);
                      end else begin
                        Envir.m_MapFlag.boEXPRATE := False;
                      end;
                    end else
                      if CompareText(sMapMode, 'PKWINLEVEL') = 0 then begin
                        if (sParam1 <> '') then begin
                          Envir.m_MapFlag.boPKWINLEVEL := True;
                          Envir.m_MapFlag.nPKWINLEVEL := Str_ToInt(sParam1, -1);
                        end else begin
                          Envir.m_MapFlag.boPKWINLEVEL := False;
                        end;
                      end else
                        if CompareText(sMapMode, 'PKWINEXP') = 0 then begin
                          if (sParam1 <> '') then begin
                            Envir.m_MapFlag.boPKWINEXP := True;
                            Envir.m_MapFlag.nPKWINEXP := Str_ToInt(sParam1, -1);
                          end else begin
                            Envir.m_MapFlag.boPKWINEXP := False;
                          end;
                        end else
                          if CompareText(sMapMode, 'PKLOSTLEVEL') = 0 then begin
                            if (sParam1 <> '') then begin
                              Envir.m_MapFlag.boPKLOSTLEVEL := True;
                              Envir.m_MapFlag.nPKLOSTLEVEL := Str_ToInt(sParam1, -1);
                            end else begin
                              Envir.m_MapFlag.boPKLOSTLEVEL := False;
                            end;
                          end else
                            if CompareText(sMapMode, 'PKLOSTEXP') = 0 then begin
                              if (sParam1 <> '') then begin
                                Envir.m_MapFlag.boPKLOSTEXP := True;
                                Envir.m_MapFlag.nPKLOSTEXP := Str_ToInt(sParam1, -1);
                              end else begin
                                Envir.m_MapFlag.boPKLOSTEXP := False;
                              end;
                            end else
                              if CompareText(sMapMode, 'DECHP') = 0 then begin
                                if (sParam1 <> '') and (sParam2 <> '') then begin
                                  Envir.m_MapFlag.boDECHP := True;
                                  Envir.m_MapFlag.nDECHPTIME := Str_ToInt(sParam1, -1);
                                  Envir.m_MapFlag.nDECHPPOINT := Str_ToInt(sParam2, -1);
                                end else begin
                                  Envir.m_MapFlag.boDECHP := False;
                                end;
                              end else
                                if CompareText(sMapMode, 'DECGAMEGOLD') = 0 then begin
                                  if (sParam1 <> '') and (sParam2 <> '') then begin
                                    Envir.m_MapFlag.boDecGameGold := True;
                                    Envir.m_MapFlag.nDECGAMEGOLDTIME :=
                                      Str_ToInt(sParam1, -1);
                                    Envir.m_MapFlag.nDecGameGold := Str_ToInt(sParam2,
                                      -1);
                                  end else begin
                                    Envir.m_MapFlag.boDecGameGold := False;
                                  end;
                                end else
                                  if CompareText(sMapMode, 'INCGAMEGOLD') = 0 then begin
                                    if (sParam1 <> '') and (sParam2 <> '') then begin
                                      Envir.m_MapFlag.boIncGameGold := True;
                                      Envir.m_MapFlag.nINCGAMEGOLDTIME :=
                                        Str_ToInt(sParam1, -1);
                                      Envir.m_MapFlag.nIncGameGold := Str_ToInt(sParam2,
                                        -1);
                                    end else begin
                                      Envir.m_MapFlag.boIncGameGold := False;
                                    end;
                                  end else
                                    if CompareText(sMapMode, 'INCGAMEPOINT') = 0 then begin
                                      if (sParam1 <> '') and (sParam2 <> '') then begin
                                        Envir.m_MapFlag.boINCGAMEPOINT := True;
                                        Envir.m_MapFlag.nINCGAMEPOINTTIME :=
                                          Str_ToInt(sParam1, -1);
                                        Envir.m_MapFlag.nINCGAMEPOINT :=
                                          Str_ToInt(sParam2, -1);
                                      end else begin
                                        Envir.m_MapFlag.boIncGameGold := False;
                                      end;
                                    end else
                                      if CompareText(sMapMode, 'RUNHUMAN') = 0 then begin
                                        if (sParam1 <> '') then begin
                                          Envir.m_MapFlag.boRUNHUMAN := True;
                                        end else begin
                                          Envir.m_MapFlag.boRUNHUMAN := False;
                                        end;
                                      end else
                                        if CompareText(sMapMode, 'RUNMON') = 0 then begin
                                          if (sParam1 <> '') then begin
                                            Envir.m_MapFlag.boRUNMON := True;
                                          end else begin
                                            Envir.m_MapFlag.boRUNMON := False;
                                          end;
                                        end else
                                          if CompareText(sMapMode, 'NEEDHOLE') =
                                            0 then begin
                                            if (sParam1 <> '') then begin
                                              Envir.m_MapFlag.boNEEDHOLE := True;
                                            end else begin
                                              Envir.m_MapFlag.boNEEDHOLE := False;
                                            end;
                                          end else
                                            if CompareText(sMapMode, 'NORECALL')
                                              = 0 then begin
                                              if (sParam1 <> '') then begin
                                                Envir.m_MapFlag.boNORECALL := True;
                                              end else begin
                                                Envir.m_MapFlag.boNORECALL := False;
                                              end;
                                            end else
                                              if CompareText(sMapMode,
                                                'NOGUILDRECALL') = 0 then begin
                                                if (sParam1 <> '') then begin
                                                  Envir.m_MapFlag.boNOGUILDRECALL :=
                                                    True;
                                                end else begin
                                                  Envir.m_MapFlag.boNOGUILDRECALL :=
                                                    False;
                                                end;
                                              end else
                                                if CompareText(sMapMode,
                                                  'NODEARRECALL') = 0 then begin
                                                  if (sParam1 <> '') then begin
                                                    Envir.m_MapFlag.boNODEARRECALL :=
                                                      True;
                                                  end else begin
                                                    Envir.m_MapFlag.boNODEARRECALL :=
                                                      False;
                                                  end;
                                                end else
                                                  if CompareText(sMapMode,
                                                    'NOMASTERRECALL') = 0 then begin
                                                    if (sParam1 <> '') then begin
                                                      Envir.m_MapFlag.boNOMASTERRECALL
                                                        := True;
                                                    end else begin
                                                      Envir.m_MapFlag.boNOMASTERRECALL
                                                        := False;
                                                    end;
                                                  end else
                                                    if CompareText(sMapMode,
                                                      'NORANDOMMOVE') = 0 then begin
                                                      if (sParam1 <> '') then begin
                                                        Envir.m_MapFlag.boNORANDOMMOVE
                                                          := True;
                                                      end else begin
                                                        Envir.m_MapFlag.boNORANDOMMOVE
                                                          := False;
                                                      end;
                                                    end else
                                                      if CompareText(sMapMode,
                                                        'NODRUG') = 0 then begin
                                                        if (sParam1 <> '') then begin
                                                          Envir.m_MapFlag.boNODRUG :=
                                                            True;
                                                        end else begin
                                                          Envir.m_MapFlag.boNODRUG :=
                                                            False;
                                                        end;
                                                      end else
                                                        if CompareText(sMapMode,
                                                          'MINE') = 0 then begin
                                                          if (sParam1 <> '') then begin
                                                            Envir.m_MapFlag.boMINE :=
                                                              True;
                                                          end else begin
                                                            Envir.m_MapFlag.boMINE :=
                                                              False;
                                                          end;
                                                        end else
                                                          if
                                                            CompareText(sMapMode,
                                                            'NOPOSITIONMOVE') = 0 then begin
                                                            if (sParam1 <> '') then begin
                                                              Envir.m_MapFlag.boNOPOSITIONMOVE
                                                                := True;
                                                            end else begin
                                                              Envir.m_MapFlag.boNOPOSITIONMOVE
                                                                := False;
                                                            end;
                                                          end else                                  //
                                                            if
                                                              CompareText(sMapMode,
                                                              'NOSTOREMOVE') = 0 then begin
                                                              if (sParam1 <> '') then begin
                                                                Envir.m_MapFlag.boNOSTOREMOVE
                                                                  := True;
                                                              end else begin
                                                                Envir.m_MapFlag.boNOSTOREMOVE
                                                                  := False;
                                                              end;
                                                            end;
  sMsg := '地图模式: ' + Envir.GetEnvirInfo;
  SysMsg(sMsg, c_Blue, t_Hint);
end;

procedure TPlayObject.CmdSetPermission(Cmd: pTGameCmd; sHumanName, sPermission:
  string);
var
  nPerission                            : Integer;
  PlayObject                            : TPlayObject;
resourcestring
  sOutFormatMsg                         = '[权限调整] %s (%s %d -> %d)';
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  nPerission := Str_ToInt(sPermission, 0);
  if (sHumanName = '') or not (nPerission in [0..10]) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称 权限等级(0 - 10)',
      c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  if g_Config.boShowMakeItemMsg then
    MainOutMessage(Format(sOutFormatMsg, [m_sCharName, PlayObject.m_sCharName,
      PlayObject.m_btPermissionGM, nPerission]));
  PlayObject.m_btPermissionGM := nPerission;
  SysMsg(sHumanName + ' 当前权限为: ' +
    IntToStr(PlayObject.m_btPermissionGM), c_Red, t_Hint);
end;

procedure TPlayObject.CmdShowDenyAccountLogon(Cmd: pTGameCmd; sAccount,
  sFixDeny: string);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < 6) then Exit;
  g_DenyAccountList.Lock;
  try
    if g_DenyAccountList.Count <= 0 then begin
      SysMsg('禁止登录帐号列表为空。', c_Green, t_Hint);
      Exit;
    end;
    for i := 0 to g_DenyAccountList.Count - 1 do begin
      SysMsg(g_DenyAccountList.Strings[i], c_Green, t_Hint);
    end;
  finally
    g_DenyAccountList.UnLock;
  end;
end;

procedure TPlayObject.CmdShowDenyCharNameLogon(Cmd: pTGameCmd; sCharName,
  sFixDeny: string);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  g_DenyChrNameList.Lock;
  try
    if g_DenyChrNameList.Count <= 0 then begin
      SysMsg('禁止登录角色列表为空。', c_Green, t_Hint);
      Exit;
    end;
    for i := 0 to g_DenyChrNameList.Count - 1 do begin
      SysMsg(g_DenyChrNameList.Strings[i], c_Green, t_Hint);
    end;
  finally
    g_DenyChrNameList.UnLock;
  end;
end;

procedure TPlayObject.CmdShowDenyIPaddrLogon(Cmd: pTGameCmd; sIPaddr,
  sFixDeny: string);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  g_DenyIPAddrList.Lock;
  try
    if g_DenyIPAddrList.Count <= 0 then begin
      SysMsg('禁止登录角色列表为空。', c_Green, t_Hint);
      Exit;
    end;
    for i := 0 to g_DenyIPAddrList.Count - 1 do begin
      SysMsg(g_DenyIPAddrList.Strings[i], c_Green, t_Hint);
    end;
  finally
    g_DenyIPAddrList.UnLock;
  end;
end;

procedure TPlayObject.CmdShowHumanFlag(sCmd: string; nPermission: Integer;
  sHumanName, sFlag: string);
var
  PlayObject                            : TPlayObject;
  nFlag                                 : Integer;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandShowHumanFlagHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  nFlag := Str_ToInt(sFlag, 0);
  if PlayObject.GetQuestFalgStatus(nFlag) = 1 then begin
    SysMsg(Format(g_sGameCommandShowHumanFlagONMsg, [PlayObject.m_sCharName,
      nFlag]), c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sGameCommandShowHumanFlagOFFMsg, [PlayObject.m_sCharName,
      nFlag]), c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdShowHumanUnit(sCmd: string; nPermission: Integer;
  sHumanName, sUnit: string);
var
  PlayObject                            : TPlayObject;
  nUnit                                 : Integer;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandShowHumanUnitHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  nUnit := Str_ToInt(sUnit, 0);
  if PlayObject.GetQuestUnitStatus(nUnit) = 1 then begin
    SysMsg(Format(g_sGameCommandShowHumanUnitONMsg, [PlayObject.m_sCharName,
      nUnit]), c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sGameCommandShowHumanUnitOFFMsg, [PlayObject.m_sCharName,
      nUnit]), c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdShowHumanUnitOpen(sCmd: string; nPermission: Integer;
  sHumanName, sUnit: string);
var
  PlayObject                            : TPlayObject;
  nUnit                                 : Integer;
begin
  if (m_btPermissionGM < nPermission) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [sCmd,
      g_sGameCommandShowHumanUnitHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  nUnit := Str_ToInt(sUnit, 0);
  if PlayObject.GetQuestUnitOpenStatus(nUnit) = 1 then begin
    SysMsg(Format(g_sGameCommandShowHumanUnitONMsg, [PlayObject.m_sCharName,
      nUnit]), c_Green, t_Hint);
  end else begin
    SysMsg(Format(g_sGameCommandShowHumanUnitOFFMsg, [PlayObject.m_sCharName,
      nUnit]), c_Green, t_Hint);
  end;
end;

procedure TPlayObject.CmdShowMapInfo(Cmd: pTGameCmd; sParam1: string);
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  SysMsg(Format(g_sGameCommandMapInfoMsg, [m_PEnvir.m_sMapName,
    m_PEnvir.m_sMapDesc]), c_Green, t_Hint);
  SysMsg(Format(g_sGameCommandMapInfoSizeMsg, [m_PEnvir.m_nWidth,
    m_PEnvir.m_nHeight]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdShowMapMode(sCmd, sMapName: string);
var
  Envir                                 : TEnvirnoment;
  sMsg                                  : string;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sMapName = '') then begin
    SysMsg('命令格式: @' + sCmd + ' 地图号', c_Red, t_Hint);
    Exit;
  end;
  Envir := g_MapManager.FindMap(sMapName);
  if (Envir = nil) then begin
    SysMsg(sMapName + ' 不存在!!!', c_Red, t_Hint);
    Exit;
  end;
  sMsg := '地图模式: ' + Envir.GetEnvirInfo;
  SysMsg(sMsg, c_Blue, t_Hint);
end;

procedure TPlayObject.CmdShowSbkGold(Cmd: pTGameCmd; sCASTLENAME, sCtr, sGold:
  string);
var
  i                                     : Integer;
  Ctr                                   : Char;
  nGold                                 : Integer;
  Castle                                : TUserCastle;
  List                                  : TStringList;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sCASTLENAME <> '') and (sCASTLENAME[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;
  if sCASTLENAME = '' then begin
    List := TStringList.Create;
    g_CastleManager.GetCastleGoldInfo(List);
    for i := 0 to List.Count - 1 do begin
      SysMsg(List.Strings[i], c_Green, t_Hint);
    end;
    List.free;
    Exit;
  end;
  Castle := g_CastleManager.Find(sCASTLENAME);
  if Castle = nil then begin
    SysMsg(Format(g_sGameCommandSbkGoldCastleNotFoundMsg, [sCASTLENAME]), c_Red,
      t_Hint);
    Exit;
  end;

  Ctr := sCtr[1];
  nGold := Str_ToInt(sGold, -1);
  if not (Ctr in ['=', '-', '+']) or (nGold < 0) or (nGold > 100000000) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandSbkGoldHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  case Ctr of
    '=': Castle.m_nTotalGold := nGold;
    '-': Dec(Castle.m_nTotalGold);
    '+': Inc(Castle.m_nTotalGold, nGold);
  end;
  if Castle.m_nTotalGold < 0 then Castle.m_nTotalGold := 0;

end;

procedure TPlayObject.CmdShowUseItemInfo(Cmd: pTGameCmd;
  sHumanName: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  UserItem                              : pTUserItem;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandShowUseItemInfoHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  for i := Low(PlayObject.m_UseItems) to High(PlayObject.m_UseItems) do begin
    UserItem := @PlayObject.m_UseItems[i];
    if UserItem.wIndex = 0 then Continue;
    SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d]',
      [GetUseItemName(i),
      UserEngine.GetStdItemName(UserItem.wIndex),
        UserItem.wIndex,
        UserItem.MakeIndex,
        UserItem.Dura,
        UserItem.DuraMax]),
        c_Blue, t_Hint);
  end;
end;

procedure TPlayObject.CmdShutup(Cmd: pTGameCmd; sHumanName, sTime: string);
var
  dwTime                                : LongWord;
  nIndex                                : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sTime = '') or (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1]
    = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandShutupHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  dwTime := Str_ToInt(sTime, 5);
  g_DenySayMsgList.Lock;
  try
    nIndex := g_DenySayMsgList.GetIndex(sHumanName);
    if nIndex >= 0 then begin
      g_DenySayMsgList.Objects[nIndex] := TObject(GetTickCount + dwTime * 60 *
        1000);
    end else begin
      g_DenySayMsgList.AddRecord(sHumanName, GetTickCount + dwTime * 60 * 1000);
    end;
  finally
    g_DenySayMsgList.UnLock;
  end;
  SysMsg(Format(g_sGameCommandShutupHumanMsg, [sHumanName, dwTime]), c_Red,
    t_Hint);
end;

procedure TPlayObject.CmdShutupList(Cmd: pTGameCmd; sParam1: string);
var
  i                                     : Integer;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd, '']), c_Red, t_Hint);
    Exit;
  end;

  if (m_btPermissionGM < 6) then Exit;
  g_DenySayMsgList.Lock;
  try
    if g_DenySayMsgList.Count <= 0 then begin
      SysMsg(g_sGameCommandShutupListIsNullMsg, c_Green, t_Hint);
      Exit;
    end;
    for i := 0 to g_DenySayMsgList.Count - 1 do begin
      SysMsg(g_DenySayMsgList.Strings[i] + ' ' +
        IntToStr((LongWord(g_DenySayMsgList.Objects[i]) - GetTickCount) div
        60000), c_Green, t_Hint);
    end;
  finally
    g_DenySayMsgList.UnLock;
  end;
end;

procedure TPlayObject.CmdShutupRelease(Cmd: pTGameCmd; sHumanName: string;
  boAll: Boolean);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandShutupReleaseHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  g_DenySayMsgList.Lock;
  try
    i := g_DenySayMsgList.GetIndex(sHumanName);
    if i >= 0 then begin
      g_DenySayMsgList.Delete(i);
      PlayObject := UserEngine.GetPlayObject(sHumanName);
      if PlayObject <> nil then begin
        PlayObject.SysMsg(g_sGameCommandShutupReleaseCanSendMsg, c_Red, t_Hint);
      end;
      if boAll then begin
        UserEngine.SendServerGroupMsg(SS_210, g_Config.nServerNumber, sHumanName);
      end;
      SysMsg(Format(g_sGameCommandShutupReleaseHumanCanSendMsg, [sHumanName]),
        c_Green, t_Hint);
    end;
  finally
    g_DenySayMsgList.UnLock;
  end;
end;

procedure TPlayObject.CmdSmakeItem(Cmd: pTGameCmd; nWhere, nValueType: Integer;
  sOpCode: string; nValue: Integer);
var
  sShowMsg                              : string;
  nValType, nPoint, nAddPoint           : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nOldOverLap                           : DWORD;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  nValType := nValueType;
  nAddPoint := nValue;

  if (nWhere >= 0) and (nWhere <= High(THumItems)) then
    UserItem := @m_UseItems[nWhere]
  else
    GetUserItemByMakeIndex(nWhere, UserItem);

  if (UserItem = nil) or (UserItem.wIndex = 0) then
    StdItem := nil
  else
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);

  if (StdItem = nil) or (sOpCode = '') or ((sOpCode <> '') and (not (sOpCode[1] in ['+', '-', '=']))) then begin
    SysMsg(g_sGamecommandSuperMakeHelpMsg, c_Red, t_Hint);
    SysMsg('命令格式: @' + Cmd.sCmd + ' 物品(位置: 0..14)编号 属性类型(0..72) 操作符号(+、-、=) 调整数值', c_Red, t_Hint);
    Exit;
  end;

  case nValType of
    0..12, 15..19: begin                                                                            //极品属性,扩展属性
        nAddPoint := _MIN(High(byte), nAddPoint);
        case sOpCode[1] of
          '+': begin
              if UserItem.btValue[nValType] + nAddPoint > High(byte) then begin
                nAddPoint := High(byte) - UserItem.btValue[nValType]
              end;
              UserItem.btValue[nValType] := UserItem.btValue[nValType] +
                nAddPoint;
            end;
          '-': begin
              if UserItem.btValue[nValType] - nAddPoint < 0 then
                UserItem.btValue[nValType] := 0
              else
                UserItem.btValue[nValType] := UserItem.btValue[nValType] -
                  nAddPoint;
            end;
          '=': begin
              UserItem.btValue[nValType] := nAddPoint;
            end;
        end;
      end;
    13: ;                                                                                           //自定义装备名称
    20: begin
        case sOpCode[1] of
          '+': begin
              if UserItem.Dura + nAddPoint > High(word) then begin
                nAddPoint := High(word) - UserItem.Dura;
              end;
              UserItem.Dura := UserItem.Dura + nAddPoint;
            end;
          '-': begin
              if UserItem.Dura - nAddPoint < 0 then begin
                nAddPoint := UserItem.Dura;
              end;
              UserItem.Dura := UserItem.Dura - nAddPoint;
            end;
          '=': begin
              UserItem.Dura := nAddPoint;
            end;
        end;
      end;
    21: begin
        case sOpCode[1] of
          '+': begin
              if UserItem.DuraMax + nAddPoint > High(word) then begin
                nAddPoint := High(word) - UserItem.DuraMax;
              end;
              UserItem.DuraMax := UserItem.DuraMax + nAddPoint;
            end;
          '-': begin
              if UserItem.DuraMax - nAddPoint < 0 then begin
                nAddPoint := UserItem.DuraMax;
              end;
              UserItem.DuraMax := UserItem.DuraMax - nAddPoint;
            end;
          '=': begin
              UserItem.DuraMax := nAddPoint;
            end;
        end;
      end;
    22: begin                                                                                       //黑暗魔力
        case sOpCode[1] of
          '+': begin
              if MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]) +
                nAddPoint > High(word) then
                nAddPoint := High(word)
              else
                nAddPoint := MakeWord(UserItem.btItemExt[0],
                  UserItem.btItemExt[1]) + nAddPoint;
              UserItem.btItemExt[0] := LoByte(nAddPoint);
              UserItem.btItemExt[1] := HiByte(nAddPoint);
            end;
          '-': begin
              if MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]) -
                nAddPoint < 0 then
                nAddPoint := 0
              else
                nAddPoint := MakeWord(UserItem.btItemExt[0],
                  UserItem.btItemExt[1]) - nAddPoint;
              UserItem.btItemExt[0] := LoByte(nAddPoint);
              UserItem.btItemExt[1] := HiByte(nAddPoint);
            end;
          '=': begin
              UserItem.btItemExt[0] := LoByte(nAddPoint);
              UserItem.btItemExt[1] := HiByte(nAddPoint);
            end;
        end;
      end;
    23..38: begin                                                                                   //黑暗属性下限
        nValType := nValType - 23;
        case sOpCode[1] of
          '+': begin
              if _Hi(UserItem.btItemExt[nValType]) + nAddPoint > $0F then
                nAddPoint := $0F
              else
                nAddPoint := _Hi(UserItem.btItemExt[nValType]) + nAddPoint;
              UserItem.btItemExt[nValType] :=
                _SetHi(UserItem.btItemExt[nValType], nAddPoint);
            end;
          '-': begin
              if _Hi(UserItem.btItemExt[nValType]) < nAddPoint then
                nAddPoint := $00
              else
                nAddPoint := _Hi(UserItem.btItemExt[nValType]) - nAddPoint;
              UserItem.btItemExt[nValType] :=
                _SetHi(UserItem.btItemExt[nValType], nAddPoint);
            end;
          '=': begin
              UserItem.btItemExt[nValType] :=
                _SetHi(UserItem.btItemExt[nValType], nAddPoint);
            end;
        end;
      end;
    39..54: begin                                                                                   //黑暗属性上限
        nValType := nValType - 39;
        case sOpCode[1] of
          '+': begin
              if _Lo(UserItem.btItemExt[nValType]) + nAddPoint > $0F then
                nAddPoint := $0F
              else
                nAddPoint := _Lo(UserItem.btItemExt[nValType]) + nAddPoint;
              UserItem.btItemExt[nValType] :=
                _SetLo(UserItem.btItemExt[nValType], nAddPoint);
            end;
          '-': begin
              if _Lo(UserItem.btItemExt[nValType]) < nAddPoint then
                nAddPoint := $00
              else
                nAddPoint := _Lo(UserItem.btItemExt[nValType]) - nAddPoint;
              UserItem.btItemExt[nValType] :=
                _SetLo(UserItem.btItemExt[nValType], nAddPoint);
            end;
          '=': begin
              UserItem.btItemExt[nValType] :=
                _SetLo(UserItem.btItemExt[nValType], nAddPoint);
            end;
        end;
      end;
    66: begin
        nValType := nValType - 55;
        case sOpCode[1] of
          '+': begin
              if UserItem.btItemExt[nValType] + nAddPoint > $FF then
                nAddPoint := $FF
              else
                nAddPoint := UserItem.btItemExt[nValType] + nAddPoint;
              UserItem.btItemExt[nValType] := nAddPoint + StdItem.NeedLevel;
            end;
          '-': begin
              if UserItem.btItemExt[nValType] < nAddPoint then
                nAddPoint := $00
              else
                nAddPoint := UserItem.btItemExt[nValType] - nAddPoint;
              UserItem.btItemExt[nValType] := nAddPoint;
            end;
          '=': begin
              UserItem.btItemExt[nValType] := nAddPoint;
            end;
        end;
      end;
    55..65, 67..70: begin
        nValType := nValType - 55;
        case sOpCode[1] of
          '+': begin
              if UserItem.btItemExt[nValType] + nAddPoint > $FF then
                nAddPoint := $FF
              else
                nAddPoint := UserItem.btItemExt[nValType] + nAddPoint;
              UserItem.btItemExt[nValType] := nAddPoint;
            end;
          '-': begin
              if UserItem.btItemExt[nValType] < nAddPoint then
                nAddPoint := $00
              else
                nAddPoint := UserItem.btItemExt[nValType] - nAddPoint;
              UserItem.btItemExt[nValType] := nAddPoint;
            end;
          '=': begin
              UserItem.btItemExt[nValType] := nAddPoint;
            end;
        end;
      end;
    71: begin                                                                                       //重叠物品、神秘符石
        nOldOverLap := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        case sOpCode[1] of
          '+': begin
              if nOldOverLap + nAddPoint > High(DWORD) then
                nAddPoint := High(DWORD)
              else
                nAddPoint := nOldOverLap + nAddPoint;
              UserItem.btValue[0] := LoByte(LoWord(nAddPoint));
              UserItem.btValue[1] := HiByte(LoWord(nAddPoint));
              UserItem.btValue[2] := LoByte(HiWord(nAddPoint));
              UserItem.btValue[3] := HiByte(HiWord(nAddPoint));
            end;
          '-': begin
              if nOldOverLap - nAddPoint < 0 then
                nAddPoint := 0
              else
                nAddPoint := nOldOverLap - nAddPoint;
              UserItem.btValue[0] := LoByte(LoWord(nAddPoint));
              UserItem.btValue[1] := HiByte(LoWord(nAddPoint));
              UserItem.btValue[2] := LoByte(HiWord(nAddPoint));
              UserItem.btValue[3] := HiByte(HiWord(nAddPoint));
            end;
          '=': begin
              UserItem.btValue[0] := LoByte(LoWord(nAddPoint));
              UserItem.btValue[1] := HiByte(LoWord(nAddPoint));
              UserItem.btValue[2] := LoByte(HiWord(nAddPoint));
              UserItem.btValue[3] := HiByte(HiWord(nAddPoint));
            end;
        end;
      end;
    72: begin                                                                                       //魂珠积累经验
        nOldOverLap := MakeLong(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]), MakeWord(UserItem.btItemExt[2], UserItem.btItemExt[3]));
        case sOpCode[1] of
          '+': begin
              nAddPoint := nOldOverLap + nAddPoint;
              UserItem.btItemExt[0] := LoByte(LoWord(nAddPoint));
              UserItem.btItemExt[1] := HiByte(LoWord(nAddPoint));
              UserItem.btItemExt[2] := LoByte(HiWord(nAddPoint));
              UserItem.btItemExt[3] := HiByte(HiWord(nAddPoint));
            end;
          '-': begin
              if nOldOverLap - nAddPoint < 0 then
                nAddPoint := 0
              else
                nAddPoint := nOldOverLap - nAddPoint;
              UserItem.btItemExt[0] := LoByte(LoWord(nAddPoint));
              UserItem.btItemExt[1] := HiByte(LoWord(nAddPoint));
              UserItem.btItemExt[2] := LoByte(HiWord(nAddPoint));
              UserItem.btItemExt[3] := HiByte(HiWord(nAddPoint));
            end;
          '=': begin
              UserItem.btItemExt[0] := LoByte(LoWord(nAddPoint));
              UserItem.btItemExt[1] := HiByte(LoWord(nAddPoint));
              UserItem.btItemExt[2] := LoByte(HiWord(nAddPoint));
              UserItem.btItemExt[3] := HiByte(HiWord(nAddPoint));
            end;
        end;
      end;

  end;
  RecalcAbilitys();
  SendUpdateItem(UserItem);
  sShowMsg := IntToStr(UserItem.wIndex) + '-' + IntToStr(UserItem.MakeIndex) +
    ' ' +
    IntToStr(UserItem.Dura) + '/' + IntToStr(UserItem.DuraMax) + ' ' +
    IntToStr(UserItem.btValue[0]) + '/' +
    IntToStr(UserItem.btValue[1]) + '/' +
    IntToStr(UserItem.btValue[2]) + '/' +
    IntToStr(UserItem.btValue[3]) + '/' +
    IntToStr(UserItem.btValue[4]) + '/' +
    IntToStr(UserItem.btValue[5]) + '/' +
    IntToStr(UserItem.btValue[6]) + '/' +
    IntToStr(UserItem.btValue[7]) + '/' +
    IntToStr(UserItem.btValue[8]) + '/' +
    IntToStr(UserItem.btValue[9]) + '/' +
    IntToStr(UserItem.btValue[10]) + '/' +
    IntToStr(UserItem.btValue[11]) + '/' +
    IntToStr(UserItem.btValue[12]) + '/' +
    IntToStr(UserItem.btValue[13]) + '/' +
    IntToStr(UserItem.btValue[14]) + '/' +
    IntToStr(UserItem.btValue[15]) + '/' +
    IntToStr(UserItem.btValue[16]) + '/' +
    IntToStr(UserItem.btValue[17]) + '/' +
    IntToStr(UserItem.btValue[18]) + '/' +
    IntToStr(UserItem.btValue[19]);
  SysMsg(sShowMsg, c_Blue, t_Hint);
  if g_Config.boShowMakeItemMsg then
    MainOutMessage('[物品调整] ' + m_sCharName + '(' + StdItem.Name + ' -> '
      + sShowMsg + ')');
end;

procedure TPlayObject.CmdSpirtStart(sCmd, sParam1: string);
var
  nTime                                 : Integer;
  dwTime                                : LongWord;
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sParam1 <> '') and (sParam1[1] = '?') then begin
    SysMsg('此命令用于开始祈祷生效宝宝叛变。', c_Red, t_Hint);
    Exit;
  end;
  nTime := Str_ToInt(sParam1, -1);
  if nTime > 0 then begin
    dwTime := LongWord(nTime) * 1000;
  end else begin
    dwTime := g_Config.dwSpiritMutinyTime;
  end;

  g_dwSpiritMutinyTick := GetTickCount + dwTime;
  SysMsg('祈祷叛变已开始。持续时长 ' + IntToStr(dwTime div 1000) + ' 秒。', c_Green, t_Hint);
end;

procedure TPlayObject.CmdSpirtStop(sCmd, sParam1: string);
begin
  if (m_btPermissionGM < 6) then Exit;
  if (sParam1 <> '') and (sParam1[1] = '?') then begin
    SysMsg('此命令用于停止祈祷生效导致宝宝叛变。', c_Red,
      t_Hint);
    Exit;
  end;
  g_dwSpiritMutinyTick := 0;
  SysMsg('祈祷叛变已停止。', c_Green, t_Hint);

end;

procedure TPlayObject.CmdStartContest(Cmd: pTGameCmd; sParam1: string);
//004CF008
var
  i, ii                                 : Integer;
  List10, List14                        : TList;
  PlayObject, PlayObjectA               : TPlayObject;
  bo19                                  : Boolean;
  s20                                   : string;
  Guild                                 : TGuild;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if ((sParam1 <> '') and (sParam1[1] = '?')) then begin
    SysMsg('开始行会争霸赛。', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s', [Cmd.sCmd]), c_Red, t_Hint);
    Exit;
  end;

  if not m_PEnvir.m_MapFlag.boFight3 then begin
    SysMsg('此命令不能在当前地图中使用!!!', c_Red, t_Hint);
    Exit;
  end;
  List10 := TList.Create;
  List14 := TList.Create;
  UserEngine.GetMapRageHuman(m_PEnvir, m_nCurrX, m_nCurrY, 1000, List10);
  for i := 0 to List10.Count - 1 do begin
    PlayObject := TPlayObject(List10.Items[i]);
    if not PlayObject.m_boObMode or not PlayObject.m_boAdminMode then begin
      PlayObject.m_nFightZoneDieCount := 0;
      if PlayObject.m_MyGuild = nil then Continue;
      bo19 := False;
      for ii := 0 to List14.Count - 1 do begin
        PlayObjectA := TPlayObject(List14.Items[ii]);
        if PlayObject.m_MyGuild = PlayObjectA.m_MyGuild then
          bo19 := True;
      end;
      if not bo19 then begin
        List14.Add(PlayObject.m_MyGuild);
      end;
    end;
  end;
  SysMsg('行会争霸赛已经开始。', c_Green, t_Hint);
  UserEngine.CryCry(RM_CRY, m_PEnvir, m_nCurrX, m_nCurrY, 1000, g_Config.btCryMsgFColor, g_Config.btCryMsgBColor, '- 行会战争已爆发。');
  s20 := '';
  for i := 0 to List14.Count - 1 do begin
    Guild := TGuild(List14.Items[i]);
    Guild.StartTeamFight();
    for ii := 0 to List10.Count - 1 do begin
      PlayObject := TPlayObject(List10.Items[i]);
      if PlayObject.m_MyGuild = Guild then begin
        Guild.AddTeamFightMember(PlayObject.m_sCharName);
      end;
    end;
    s20 := s20 + Guild.sGuildName + ' ';
  end;
  UserEngine.CryCry(RM_CRY, m_PEnvir, m_nCurrX, m_nCurrY, 1000,
    g_Config.btCryMsgFColor, g_Config.btCryMsgBColor, ' -参加的门派:' + s20);
  List10.free;
  List14.free;
end;

procedure TPlayObject.CmdStartQuest(Cmd: pTGameCmd; sQuestName, sMapName: string);
var
  Map                                   : TEnvirnoment;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sQuestName = '') then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 问答名称 地图名称', c_Red, t_Hint);
    Exit;
  end;
  if (sMapName <> '') then
    Map := g_MapManager.FindMap(sMapName)
  else
    Map := nil;
  UserEngine.SendQuestMsg(sQuestName, Map);
end;

procedure TPlayObject.CmdSuperTing(Cmd: pTGameCmd; sHumanName, sRange: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  MoveHuman                             : TPlayObject;
  nRange                                : Integer;
  HumanList                             : TList;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sRange = '') or (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1]
    = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandSuperTingHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  nRange := _Max(10, Str_ToInt(sRange, 2));
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    HumanList := TList.Create;
    UserEngine.GetMapRageHuman(PlayObject.m_PEnvir, PlayObject.m_nCurrX,
      PlayObject.m_nCurrY, nRange, HumanList);
    for i := 0 to HumanList.Count - 1 do begin
      MoveHuman := TPlayObject(HumanList.Items[i]);
      if MoveHuman <> Self then
        MoveHuman.MapRandomMove(MoveHuman.m_sHomeMap, 0, nil);
    end;
    HumanList.free;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;

end;

procedure TPlayObject.CmdTakeOffHorse(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('下马命令,在骑马状态输入此命令下马。', c_Red,
      t_Hint);
    SysMsg(Format('命令格式: @%s', [sCmd]), c_Red, t_Hint);
    Exit;
  end;
  if m_boRideOn then ClientRideOff;
  FeatureChanged();
end;

procedure TPlayObject.CmdTakeOnHorse(sCmd, sParam: string);
begin
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg('上马命令,在戴好马牌后输入此命令就可以骑上马。', c_Red, t_Hint);
    SysMsg(Format('命令格式: @%s', [sCmd]), c_Red, t_Hint);
    Exit;
  end;
  if (m_btHorseType = 0) then begin
    SysMsg('骑马必须先戴上马牌!!!', c_Red, t_Hint);
    Exit;
  end;
  FeatureChanged();
end;

procedure TPlayObject.CmdTestFire(sCmd: string; nRange, nType, nTime, nPoint:
  Integer);
var
  nX, nY                                : Integer;
  FireBurnEvent                         : TFireBurnEvent;
  nMinX, nMaxX, nMinY, nMaxY            : Integer;
begin
  nMinX := m_nCurrX - nRange;
  nMaxX := m_nCurrX + nRange;
  nMinY := m_nCurrY - nRange;
  nMaxY := m_nCurrY + nRange;
  for nX := nMinX to nMaxX do begin
    for nY := nMinY to nMaxY do begin
      if ((nX < nMaxX) and (nY = nMinY)) or
        ((nY < nMaxY) and (nX = nMinX)) or
        (nX = nMaxX) or (nY = nMaxY) then begin
        FireBurnEvent := TFireBurnEvent.Create(Self, nX, nY, nType, nTime *
          1000, nPoint);
        g_EventManager.AddEvent(FireBurnEvent);
      end;
    end;
  end;
end;

procedure TPlayObject.CmdTestGetBagItems(Cmd: pTGameCmd; sParam: string);
var
  btDc, btSc, btMc, btDura              : byte;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sParam <> '') and (sParam[1] = '?') then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandTestGetBagItemsHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  btDc := 0;
  btSc := 0;
  btMc := 0;
  btDura := 0;
  GetBagUseItems(btDc, btSc, btMc, btDura);
  SysMsg(Format('DC:%d SC:%d MC:%d DURA:%d', [btDc, btSc, btMc, btDura]),
    c_Blue, t_Hint);
end;

procedure TPlayObject.CmdTestSpeedMode(Cmd: pTGameCmd; nWhere, nType: Integer);
var
  CharStatus                            : TCharStatus;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  m_boTestSpeedMode := not m_boTestSpeedMode;
  if m_boTestSpeedMode then begin
    SysMsg('开启速度测试模式', c_Red, t_Hint);
  end else begin
    SysMsg('关闭速度测试模式', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdTestStatus(sCmd: string; nType, nTime: Integer);
begin
  if (m_btPermissionGM < 6) then Exit;
  if (not (nType in [Low(TStatusTime)..High(TStatusTime)])) or (nTime < 0) then begin
    SysMsg('命令格式: @' + sCmd + ' 类型(0..11) 时长', c_Red, t_Hint);
    Exit;
  end;
  m_wStatusTimeArr[nType] := _MIN(60, nTime) * 1000;
  m_dwStatusArrTick[nType] := GetTickCount();
  m_nCharStatus := GetCharStatus();
  StatusChanged();
  if g_Config.boShowScriptActionMsg then
    SysMsg(Format('状态编号:%d 时间长度: %d 秒', [nType, nTime]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdTing(Cmd: pTGameCmd; sHumanName: string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or ((sHumanName <> '') and (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandTingHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject <> nil then begin
    PlayObject.MapRandomMove(m_sHomeMap, 0, nil);
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdTraining(sSkillName: string; nLevel: Integer);
//004CC414
begin
  if (m_btPermissionGM < 6) then Exit;
end;

//GM命令TrainingSkill 人物 技能名称 修炼等级

procedure TPlayObject.CmdTrainingMagic(Cmd: pTGameCmd; sHumanName, sSkillName:
  string;
  nLevel: Integer);
var
  Magic                                 : pTMagic;
  PlayObject                            : TPlayObject;
  btLevel                               : byte;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;

  if ((sHumanName <> '') and (sHumanName[1] = '?')) or (sHumanName = '') or
    (sSkillName = '') or (nLevel < 0) or not (nLevel in [0..SKILLMAXLEVEL]) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称  技能名称 修炼等级(0-' + IntToStr(SKILLMAXLEVEL), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;

  Magic := UserEngine.FindMagic(sSkillName);
  if Magic = nil then begin
    SysMsg(Format('%s 技能名称不正确!!!', [sSkillName]), c_Red, t_Hint);
    Exit;
  end;

  if PlayObject.IsTrainingSkill(Magic.wMagicID) then begin
    SysMsg(Format('%s的%s 技能已修炼过了!!!', [PlayObject.m_sCharName, sSkillName]), c_Red, t_Hint);
    Exit;
  end;

  if (Magic.wMagicID in [87..90]) and (nLevel = 0) then
    btLevel := _Max(1, nLevel)
  else
    btLevel := nLevel;
  PlayObject.AddItemSkill(Magic, nLevel, 0, 0);
  PlayObject.RecalcAbilitys;
  SysMsg(Format('%s 的 %s 技能修炼成功!!!', [PlayObject.m_sCharName, sSkillName]), c_Green, t_Hint);
end;

//调整人物技能等级

procedure TPlayObject.CmdTrainingSkill(Cmd: pTGameCmd; sHumanName, sSkillName:
  string;
  nLevel: Integer);
var
  i                                     : Integer;
  UserMagic                             : pTUserMagic;
  PlayObject                            : TPlayObject;
  Found                                 : Boolean;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sHumanName = '') or (sSkillName = '') or (nLevel < 0) or (nLevel > SKILLMAXLEVEL) then begin
    SysMsg('命令格式: @' + Cmd.sCmd + ' 人物名称  技能名称 修炼等级(0-' + IntToStr(SKILLMAXLEVEL) + ')', c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format('%s不在线,或在其它服务器上!!', [sHumanName]), c_Red, t_Hint);
    Exit;
  end;

  Found := False;
  for i := 0 to PlayObject.m_MagicList.Count - 1 do begin
    UserMagic := PlayObject.m_MagicList.Items[i];
    if (CompareText(UserMagic.MagicInfo.sMagicName, sSkillName) = 0) and (UserMagic.btType < MAG_AMALGAMATION) then begin
      if UserMagic.GetMagIdx in [87..90] then nLevel := _Max(1, nLevel);
      UserMagic.btLevel := nLevel;
      PlayObject.SendMagic_LvExp_Msg(UserMagic, 100);

      PlayObject.SysMsg(Format('%s的修炼等级为%d', [sSkillName, nLevel]), c_Green, t_Hint);
      SysMsg(Format('%s的技能%s修炼等级为%d', [sHumanName, sSkillName, nLevel]), c_Green, t_Hint);
      Found := True;
      Break;
    end;
  end;
  if not Found then
    SysMsg(Format('%s的技能%s尚未修炼', [sHumanName, sSkillName]), c_Green, t_Hint);
end;

procedure TPlayObject.CmdUnBindUseItem(Cmd: pTGameCmd; sHumanName, sItem,
  sType: string);
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  UserItem                              : pTUserItem;
  nItem, nBind                          : Integer;
  ItemBind                              : pTItemBind;
  nItemIdx, nMakeIdex                   : Integer;
  sBindName                             : string;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  nBind := -1;
  nItem := GetUseItemIdx(sItem);
  if CompareText(sType, '帐号') = 0 then nBind := 0;
  if CompareText(sType, '人物') = 0 then nBind := 1;
  if CompareText(sType, 'IP') = 0 then nBind := 2;

  if (nItem < 0) or (nBind < 0) or (sHumanName = '') or ((sHumanName <> '') and
    (sHumanName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandBindUseItemHelpMsg]), c_Red, t_Hint);
    Exit;
  end;

  PlayObject := UserEngine.GetPlayObject(sHumanName);
  if PlayObject = nil then begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumanName]), c_Red, t_Hint);
    Exit;
  end;
  UserItem := @PlayObject.m_UseItems[nItem];
  if UserItem.wIndex = 0 then begin
    SysMsg(Format(g_sGameCommandBindUseItemNoItemMsg, [sHumanName, sItem]),
      c_Red, t_Hint);
    Exit;
  end;
  nItemIdx := UserItem.wIndex;
  nMakeIdex := UserItem.MakeIndex;
  case nBind of                                                                                     //
    0: begin
        sBindName := PlayObject.m_sUserID;

        for i := 0 to g_ItemBindAccount.Count - 1 do begin
          ItemBind := g_ItemBindAccount.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName,
              sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindAccount.Insert(0, ItemBind);

        SaveItemBindAccount();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
    1: begin
        sBindName := PlayObject.m_sCharName;

        for i := 0 to g_ItemBindCharName.Count - 1 do begin
          ItemBind := g_ItemBindCharName.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName,
              sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindCharName.Insert(0, ItemBind);

        SaveItemBindCharName();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
    2: begin
        sBindName := PlayObject.m_sIPaddr;

        for i := 0 to g_ItemBindIPaddr.Count - 1 do begin
          ItemBind := g_ItemBindIPaddr.Items[i];
          if (ItemBind.nItemIdx = nItemIdx) and (ItemBind.nMakeIdex = nMakeIdex) then begin
            SysMsg(Format(g_sGameCommandBindUseItemAlreadBindMsg, [sHumanName,
              sItem]), c_Red, t_Hint);
            Exit;
          end;
        end;
        New(ItemBind);
        ItemBind.nItemIdx := nItemIdx;
        ItemBind.nMakeIdex := nMakeIdex;
        ItemBind.sBindName := sBindName;
        g_ItemBindIPaddr.Insert(0, ItemBind);

        SaveItemBindIPaddr();
        SysMsg(Format('%s[%s]IDX[%d]系列号[%d]持久[%d-%d],绑定到%s成功。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            UserItem.wIndex,
            UserItem.MakeIndex,
            UserItem.Dura,
            UserItem.DuraMax,
            sBindName]),
            c_Blue, t_Hint);
        PlayObject.SysMsg(Format('你的%s[%s]已经绑定到%s[%s]上了。',
          [GetUseItemName(nItem),
          UserEngine.GetStdItemName(UserItem.wIndex),
            sType,
            sBindName
            ]), c_Blue, t_Hint);
      end;
  end;
end;

procedure TPlayObject.CmdUserMoveXY(sCmd, sX, sY: string);
var
  nX, nY                                : Integer;
begin
  if m_boTeleport then begin
    nX := Str_ToInt(sX, -1);
    nY := Str_ToInt(sY, -1);
    if not m_PEnvir.m_MapFlag.boNOPOSITIONMOVE then begin
      if m_PEnvir.CanWalkOfItem(nX, nY, g_Config.boUserMoveCanDupObj,
        g_Config.boUserMoveCanOnItem) then begin
        if (GetTickCount - m_dwTeleportTick) > g_Config.dwUserMoveTime * 1000
          {10000}then begin
          m_dwTeleportTick := GetTickCount();
          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
          //BaseObjectMove('',sX,sY);
          SpaceMove(m_sMapName, nX, nY, 0, nil);
        end else begin
          SysMsg(IntToStr(g_Config.dwUserMoveTime - (GetTickCount -
            m_dwTeleportTick) div 1000) +
            '秒之后才可以再使用此功能!!!', c_Red, t_Hint);
        end;
      end else begin
        SysMsg(Format(g_sGameCommandPositionMoveCanotMoveToMap, [m_sMapName, sX,
          sY]), c_Green, t_Hint);
      end;
    end else begin
      SysMsg('此地图禁止使用此命令!!!', c_Red, t_Hint);
    end;
  end else begin
    SysMsg('您现在还无法使用此功能!!!', c_Red, t_Hint);
  end;
end;

procedure TPlayObject.CmdViewDiary(sCmd: string; nFlag: Integer);
begin

end;

procedure TPlayObject.CmdViewWhisper(Cmd: pTGameCmd; sCharName, sParam2:
  string);
var
  PlayObject                            : TPlayObject;
begin
  if (m_btPermissionGM < Cmd.nPermissionMin) then begin
    SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
    Exit;
  end;
  if (sCharName = '') or ((sCharName <> '') and (sCharName[1] = '?')) then begin
    SysMsg(Format(g_sGameCommandParamUnKnow, [Cmd.sCmd,
      g_sGameCommandViewWhisperHelpMsg]), c_Red, t_Hint);
    Exit;
  end;
  PlayObject := UserEngine.GetPlayObject(sCharName);
  if PlayObject <> nil then begin
    if PlayObject.m_GetWhisperHuman = Self then begin
      PlayObject.m_GetWhisperHuman := nil;
      SysMsg(Format(g_sGameCommandViewWhisperMsg1, [sCharName]), c_Green,
        t_Hint);
    end else begin
      PlayObject.m_GetWhisperHuman := Self;
      SysMsg(Format(g_sGameCommandViewWhisperMsg2, [sCharName]), c_Green,
        t_Hint);
    end;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sCharName]), c_Red, t_Hint);
  end;
end;

{元神创建结束}

procedure TPlayObject.CreatePneumaEnd(btFlag: Integer; sNewName: string; nSex, btHumKind: byte);
begin
  if btFlag = 1 then begin
    if btHumKind = 1 then begin
      m_sPneumaName := sNewName;
      if m_PneumaObject = nil then
        m_btPneumaSex := nSex + 1;
    end;
    Inc(m_btCurPneumaCount);
    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    if not ExecuteScript(g_FunctionNPC, '@元神创建成功') then
      SysMsg('元神创建成功!', c_Red, t_Hint);
  end else begin
    if not ExecuteScript(g_FunctionNPC, '@元神创建失败') then
      SysMsg('元神创建失败,名字可能被占用,请换一个名字!', c_Red, t_Hint);
  end;
  m_boCreatePneuma := False;
end;

function TPlayObject.DayBright: byte;
begin
  Result := 0;
  if m_PEnvir.m_boDarkness then
    Result := 1
  else if m_PEnvir.m_boDayLight then Result := 0;
end;

procedure TPlayObject.DealCancel;
begin
  if not m_boDealing then Exit;
  m_boDealing := False;
  SendDefMessage(SM_DEALCANCEL, 0, 0, 0, 0, '');
  if m_DealCreat <> nil then begin
    TPlayObject(m_DealCreat).DealCancel;
  end;
  m_DealCreat := nil;
  GetBackDealItems();
  SysMsg(g_sDealActionCancelMsg {'交易取消'}, c_Green, t_Hint);
  m_DealLastTick := GetTickCount();
end;

procedure TPlayObject.DealCancelA;
begin
  m_Abil.dwHP := m_WAbil.dwHP;
  DealCancel();
end;

procedure TPlayObject.DelFromFriendList(FriendName: string);
var
  i                                     : Integer;
begin
  i := m_FriendsList.IndexOf(FriendName);
  if i < 0 then Exit;
  //在我的好友名单中删除
  m_FriendsList.Delete(i);
  SendDefMessage(SM_DelFriend, 2, 0, 0, 0, FriendName);
end;

procedure TPlayObject.DelPneuma(nIdx: Integer);
var
  pDelPneuma                            : PTSwitchPneuma;
begin
  if m_boPneuma then Exit;                                                                          //你就是元神!怎么能删除?
  if (nIdx > m_btCurPneumaCount) then begin
    SysMsg('你选择的元神以经被删除了!!!', c_Red, t_Hint);
    Exit;                                                                                           //以经没有元神了! 不能删除
  end;

  if m_PneumaObject <> nil then begin
    SysMsg('请先收起元神,再执行删除', c_Red, t_Hint);
    Exit;
  end;
  if nIdx in [1, 2] then begin
    g_LargePacketManage.Init();
    pDelPneuma := g_LargePacketManage.GetMemRecord(SizeOf(TSwitchPneuma));

    pDelPneuma^.dwPlayObject := Integer(Self);
    pDelPneuma^.sChrName := m_sPneumaName;
    pDelPneuma^.dwDBIndex := nIdx;
    FrontEngine.SendGameWorkMsg(WK_DelPneuma, 0, g_LargePacketManage.GetMsg, False, True);
  end;

  //  if (nIdx = 1) then begin
  //    if m_PneumaObject <> nil then begin
  //      SysMsg('请先收起元神,再执行删除', c_Red, t_Hint);
  //      Exit;
  //    end;
  //    if m_sPneumaName = '' then Exit;
  //    SendDelPneuma(m_sUserID, m_sPneumaName);
  //    m_btPneumaSex := 0;
  ////    m_btPneumaJob := 0;
  ////    m_wPneumaLevel := 0;
  //    m_sPneumaName := '';
  //    SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, '你的元神已经删除成功');
  //  end else begin
  ////    if m_btIntrovertSex = 0 then Exit;
  ////    m_btIntrovertSex := 0;
  ////    m_btIntrovertJob := 0;
  ////    m_wIntrovertLevel := 0;
  ////    FillChar(m_IntrovertAbil, SizeOf(TAbility), #0);
  ////    FillChar(m_IntrovertMagic, SizeOf(THumMagic), #0);
  //    if m_PneumaObject <> nil then begin
  //      m_PneumaObject.m_btPneumaKind := 1;
  //    end;
  //  end;

end;

procedure TPlayObject.DelPneumaEnd(nIdx, btSex, btCount: byte);
var
  sMsg                                  : string;
begin
  if m_boPneuma then Exit;

  if (nIdx > 0) then begin
    m_btCurPneumaCount := btCount;
    m_btPneumaSex := btSex + 1;

    if m_btCurPneumaCount = 0 then begin
      m_sPneumaName := '';
      m_btPneumaSex := 0;
      sMsg := '你的元神已经删除成功!!'
    end else if nIdx = 1 then
      sMsg := '你的外现元神已经删除成功,内敛元神以切换成了外现元神.'
    else sMsg := '你的内敛元神已经删除成功.';
    SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, sMsg);

    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  end else
    SendDefMessage(SM_MENU_OK, 0, 0, 0, 0, '你选择的元神删除失败');
end;

//从地图上消失

procedure TPlayObject.Disappear;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::Disappear';
var
  i                                     : Integer;
  nCheck                                : Integer;
begin
  nCheck := 0;
  try
    if m_boReadyRun then DisappearA;
    nCheck := 1;
    if m_boTransparent and m_boHideMode then
      m_wStatusTimeArr[STATE_TRANSPARENT {0x70}] := 0;

    nCheck := 2;
    if m_GroupOwner <> nil then begin
      m_GroupOwner.DelMember(Self);
    end;
    nCheck := 3;
    if m_MyGuild <> nil then begin
      TGuild(m_MyGuild).DelHumanObj(Self);
    end;
    nCheck := 4;
    if m_MyClan <> nil then begin
      TClan(m_MyClan).DelHumanObj(Self);
    end;
    nCheck := 5;
    //删除马
    HorseHide;
    nCheck := 6;
    //删除踏云豹
    if (m_Pet <> nil) then PetHide(m_PetInfo[0].nMakeIndex);
    nCheck := 7;
    LogonTimcCost();
    nCheck := 8;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheck]));
      MainOutMessage(E.Message);
    end;
  end;

  inherited;
end;

//人物死亡后掉落物品

procedure TPlayObject.DropUseItems(BaseObject: TBaseObject; AttackBaseObject: TBaseObject = nil);
var
  i                                     : Integer;
  nRate                                 : Integer;
  StdItem                               : pTStdItem;
  DelList                               : TStringList;
  boCon, boDrop                         : Boolean;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::DropUseItems';
begin
  boDrop := False;
  DelList := nil;
  try
    if m_boAngryRing or m_boNoDropUseItem then Exit;

    for i := Low(THumItems) to High(THumItems) do begin
      StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
      if StdItem <> nil then begin
        if CheckSPCode(StdItem.Reserved, RE_DIRCLEAR) then begin                                    //物品控制-死亡消失
          if DelList = nil then DelList := TStringList.Create;
          DelList.AddObject('', TObject(m_UseItems[i].MakeIndex));
          m_UseItems[i].wIndex := 0;
          boDrop := True;
          if StdItem.boGameLog = 1 then
            AddGameDataLog('16' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(m_UseItems[i].MakeIndex) + #9 +
              BoolToIntStr(m_btRaceServer = RC_PLAYOBJECT) + #9 +
              '0');
        end;
      end;
    end;

    for i := Low(THumItems) to High(THumItems) do begin
      if PKLevel > 2 then
        nRate := g_Config.nDieRedDropUseItemRate
      else
        nRate := g_Config.nDieDropUseItemRate;

      if AttackBaseObject <> nil then begin
        if (g_Config.boAttachedSoulAbil) then
          nRate := _MAX(0, nRate - AttackBaseObject.m_HumDropUserItemAddRate);                      //附魂
      end;

      StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
      if StdItem <> nil then begin
        boCon := CheckSPCode(StdItem.SPCode, SP_DISABLEDIEDROP) and (CheckSPCode(StdItem.Reserved, RE_DIEDROP));
        if (not boCon) and (CheckSPCode(StdItem.Reserved, RE_DIEDROP)) then
          nRate := 0;                                                                               //物品控制-死亡身上爆出
        if (Random(nRate) <> 0) and (boCon) then Continue;
        if (not boCon) and ((Random(nRate) <> 0) or (CheckSPCode(StdItem.SPCode, SP_DISABLEDIEDROP))) then Continue; //物品控制-禁止身上爆出

        if ((m_UseItems[i].btItemExt[4] and EX_BIND) = EX_BIND) then Continue;                      //绑定物品

        if DropItemDown(@m_UseItems[i], 5, True, BaseObject, Self) then begin
          //if StdItem.Reserved and 10 = 0 then begin
          if m_btRaceServer = RC_PLAYOBJECT then begin
            if DelList = nil then DelList := TStringList.Create;
            DelList.AddObject(UserEngine.GetStdItemName(m_UseItems[i].wIndex),
              TObject(m_UseItems[i].MakeIndex));
          end;
          m_UseItems[i].wIndex := 0;
          //end;
          boDrop := True;
        end;
      end;
    end;
    RecalcAbilitys(boDrop);

    if DelList <> nil then
      SendMsg(Self, RM_SENDDELITEMLIST, 0, Integer(DelList), 0, 0, '');
  except
    MainOutMessage(sExceptionMsg);
  end;
end;

function TPlayObject.EatItems(StdItem: pTStdItem): Boolean;
var
  bo06                                  : Boolean;
  nOldStatus                            : Integer;
  nHP, nMP, nTime                       : Integer;
  Magic                                 : pTMagic;
begin
  Result := False;
  if m_PEnvir.m_MapFlag.boNODRUG then begin
    SysMsg(sCanotUseDrugOnThisMap, c_Red, t_Hint);
    Exit;
  end;
  if GetTickCount - m_dwEatItemTick >= g_Config.nEatItemTime then begin
    m_dwEatItemTick := GetTickCount;
  end else
    Exit;
  case StdItem.StdMode of
    0: begin
        nHP := _MIN(High(word), LoWord(StdItem.AC)) * _Max(1, HiWord(StdItem.AC));
        nMP := _MIN(High(word), LoWord(StdItem.MAC)) * _Max(1, HiWord(StdItem.MAC));
        case StdItem.Shape of
          0, 202: begin                                                                             //普通药品
              if (StdItem.AC > 0) then begin
                Inc(m_nIncHealth, nHP);
                Inc(m_nIncHealth, m_nAllIncReply);
              end;
              if (StdItem.MAC > 0) then begin
                Inc(m_nIncSpell, nMP);
                Inc(m_nIncSpell, m_nAllIncReply);
              end;
              Result := True;
            end;
          1: begin                                                                                  //瞬间加血物品,太阳神水
              Inc(nHP, m_nAllIncReply);
              Inc(nMP, m_nAllIncReply);
              IncHealthSpell(nHP, nMP);
              Result := True;
            end;
          201: begin                                                                                //治疗神水
              if CheckEatItems(StdItem) then begin
                Inc(nHP, m_nAllIncReply);
                Inc(nMP, m_nAllIncReply);
                IncHealthSpell(nHP, nMP);
                SendRefMsg(RM_510, 1, 0, 3, 0, '');
                Result := True;
              end;
            end;
          2: begin
              m_boUserUnLockDurg := True;
              Result := True;
            end;
          3: begin
              if m_boPneuma and m_boPneumaEffMode then begin
                IncHealthSpell(nHP, nMP);
                Result := True;
              end;
            end;
          4: begin
              if m_PEnvir.m_MapFlag.boDECHP then begin
                if m_dwEatTalismanTick > 0 then
                  m_dwEatTalismanTick := m_dwEatTalismanTick + LoWord(StdItem.DC) * 60000
                else
                  m_dwEatTalismanTick := GetTickCount + LoWord(StdItem.DC) * 60000;
                SendDefMessage(SM_510, Integer(Self), (m_dwEatTalismanTick - GetTickCount) mod 1000, 0, 79, '');
                SysMsg(StdItem.FilterName + '可以让你在天魔宝藏中不受魔气侵袭而损失生命值,效果持续20分钟', c_Red, t_Hint);
                ExecuteScript(g_FunctionNPC, '@使用辟邪丹');
                Result := True;
              end else begin
                SysMsg(StdItem.FilterName + '在此地图使用没有什么效果。', c_Red, t_Hint);
              end;
            end;
          5: begin                                                                                  //强化技能灵丹
              Magic := UserEngine.FindMagic(Str_ToInt(m_sScriptParam[1], -1));
              if Magic <> nil then begin
                m_sScriptParam[1] := Magic^.sMagicName;
                m_sScriptParam[3] := IntToStr(Magic^.wMagicID);
              end else
                m_sScriptParam[1] := '';
              UseStdmodeFunItem(StdItem);
              Result := True;
            end;
          200: begin
              if CheckEatItems(StdItem) then begin
                Inc(nHP, m_nAllIncReply * 10);
                Inc(nMP, m_nAllIncReply * 10);
                nTime := LoWord(StdItem.DC);
                if nTime = 0 then nTime := 10;

                if (StdItem.AC > 0) then begin
                  m_nSuperIncHealth := nHP;
                  m_dwSuperIncHealthTick := GetTickCount + nTime * 60 * 1000;
                  SendDefMessage(SM_510, Integer(Self), 1, 0, 1, '');
                end;
                if (StdItem.MAC > 0) then begin
                  m_nSuperIncSpell := nMP;
                  m_dwSuperIncSpellTick := GetTickCount + nTime * 60 * 1000;
                  SendDefMessage(SM_510, Integer(Self), 1, 0, 2, '');
                end;
                Result := True;
              end;
            end;
          206: begin
              if (m_Tiger <> nil) and (not m_Tiger.m_boGhost) and (not m_Tiger.m_boDeath) then begin
                Inc(m_Tiger.m_WAbil.dwHP, nHP);
                m_Tiger.HealthSpellChanged();
                Result := True;
              end;
            end;
          207: begin
              if m_btJob <> 3 then begin                                                            //妖士是没有虎王盾的
                if (m_TorDDM.Tiger.DB.Dragon = 0) and (m_TorDDM.Tiger.DB.level > 0) and (m_TorDDM.Tiger.Abil.MaxHP > 0) then begin
                  m_TorDDM.Tiger.DB.ReCallTick := 0;
                  SendTigerInfo;
                  SysMsg('你的虎灵值已经恢复了。', c_Red, t_Hint);
                  Result := True;
                end;
              end;
            end;
          219: begin
              if m_btJob <> 3 then begin
                if (m_TorDDM.Tiger.DB.Dragon > 0) and (m_TorDDM.Tiger.DB.level > 0) and (m_TorDDM.Tiger.Abil.MaxHP > 0) then begin
                  m_TorDDM.Tiger.DB.ReCallTick := 0;
                  SendTigerInfo;
                  SysMsg('你的龙灵值已经恢复了。', c_Red, t_Hint);
                  Result := True;
                end;
              end;
            end;
          208: begin
              if m_btMentalLevel > 0 then begin
                if m_nMentalPoint < m_nMentalPointMax then begin
                  nHP := StdItem.NeedLevel * 100;
                  Inc(m_nMentalPoint, nHP);
                  SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
                  Result := True;
                end;
                bo06 := False;
                if (m_nMentalPoint >= m_nMentalPointMax) then begin
                  while True do begin
                    if (UserEngine.GetMentalAbil(m_btJob, m_btMentalLevel + 1) <> nil) then begin
                      if (m_nMentalPoint >= m_nMentalPointMax) and (m_nMentalPointMax > 0) then begin
                        Dec(m_nMentalPoint, m_nMentalPointMax);
                        Inc(m_btMentalLevel);
                        RecalcAbilitys();
                        bo06 := True;
                      end else
                        Break;
                    end else
                      Break;
                  end;
                  if bo06 then begin
                    ClientQueryMentalAbilitys(Self);
                    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                    FeatureChanged();
                  end;
                end;
              end else begin
                SysMsg('你还未领悟天元心法,不能使用该道具。请到魔法阵祭祀那领悟天元心法。', c_Red, t_Hint);
              end;
            end;
          211: begin                                                                                //海神生命神水
              if m_WAbil.dwHP < m_WAbil.dwMaxHP then begin
                if GetTickCount - m_dwEatDurgHPTick >= StdItem.NeedLevel * 1000 then begin
                  m_dwEatDurgHPTick := GetTickCount;
                  Result := True;
                end else begin
                  SysMsg(Format('此神水%d秒后才能使用!', [(StdItem.NeedLevel * 1000 - (GetTickCount - m_dwEatDurgHPTick)) div 1000]), c_Red, t_Hint);
                end;
              end;
            end;
          212: begin                                                                                //海神魔法神水
              if m_WAbil.dwMP < m_WAbil.dwMaxMP then begin
                if GetTickCount - m_dwEatDurgMPTick >= StdItem.NeedLevel * 1000 then begin
                  m_dwEatDurgMPTick := GetTickCount;
                  Result := True;
                end else begin
                  SysMsg(Format('此神水%d秒后才能使用!', [(StdItem.NeedLevel * 1000 - (GetTickCount - m_dwEatDurgMPTick)) div 1000]), c_Red, t_Hint);
                end;
              end;
            end;
        else begin
            UseStdmodeFunItem(StdItem);
          end;
        end;
      end;
    1: begin
        nOldStatus := GetMyStatus();
        Inc(m_nHungerStatus, StdItem.DuraMax div 10);
        m_nHungerStatus := _MIN(5000, m_nHungerStatus);
        if nOldStatus <> GetMyStatus() then RefMyStatus();
        Result := True;
      end;
    2: Result := True;
    3: begin
        case StdItem.Shape of
          12: begin
              bo06 := False;
              if LoWord(StdItem.DC) > 0 then begin
                m_wStatusArrValue[0] := LoWord(StdItem.DC);
                m_dwStatusArrTimeOutTick[0] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('攻击力增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if LoWord(StdItem.MC) > 0 then begin
                m_wStatusArrValue[1] := LoWord(StdItem.MC);
                m_dwStatusArrTimeOutTick[1] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('魔法力增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if LoByte(StdItem.SC) > 0 then begin
                m_wStatusArrValue[2] := LoWord(StdItem.SC);
                m_dwStatusArrTimeOutTick[2] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('道术增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if HiWord(StdItem.AC) > 0 then begin
                m_wStatusArrValue[3] := HiWord(StdItem.AC);
                m_dwStatusArrTimeOutTick[3] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('攻击速度增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if LoWord(StdItem.AC) > 0 then begin
                m_wStatusArrValue[4] := LoWord(StdItem.AC);
                m_dwStatusArrTimeOutTick[4] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('生命值增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if LoWord(StdItem.MAC) > 0 then begin
                m_wStatusArrValue[5] := LoWord(StdItem.MAC);
                m_dwStatusArrTimeOutTick[5] := GetTickCount + HiWord(StdItem.MAC) * 1000;
                SysMsg('魔法值增加' + IntToStr(HiWord(StdItem.MAC)) + '秒', c_Green, t_Hint);
                bo06 := True;
              end;
              if bo06 then begin
                RecalcAbilitys();
                SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                Result := True;
              end;
            end;
          16: begin                                                                                 //摊位样式
              m_wShopKind := StdItem.AC;
              SysMsg('您改变了摊位类型', c_Red, t_Hint);
              Result := True;
            end;
          17: begin
              if StdItem.AniCount = 0 then begin
                m_btShopBanner := StdItem.AC;
                m_nBannerColor := MakeLong(MakeWord(LoWord(StdItem.MAC), HiWord(StdItem.MAC)),
                  MakeWord(LoWord(StdItem.DC), HiWord(StdItem.DC)));
                SysMsg('您改变了摊位旗帜颜色', c_Red, t_Hint);
                Result := True;
              end else begin
                Result := UseStdmodeFunItem(StdItem);
              end;
            end;
          201: begin                                                                                //百变披风
              if StdItem.AniCount > 0 then begin                                                    //次数物品
                Result := UseStdmodeFunItem(StdItem);
                Exit;
              end;
              if m_boRideOn or m_boCatapultMode then begin
                SysMsg('你现在不可以使用变身披风', c_Red, t_Hint);
                Exit;
              end;
              if (StdItem.AC = m_wBianshenImg) and (StdItem.MAC = m_wBianshenAppr) then begin       //取消变身
                m_wBianshenImg := 0;
                m_wBianshenAppr := 0;
              end else begin
                m_wBianshenImg := StdItem.AC;
                m_wBianshenAppr := StdItem.MAC;
              end;
              if m_wExtraLevel > 0 then begin
                if m_wBianshenAppr = 0 then
                  SendMsg(Self, RM_FENGHAO, MakeWord(8, LoByte(m_wExtraLevel)), GetPneumaAmbit, HiByte(m_wExtraLevel), 0, GetExtraLevelName)
                else
                  SendMsg(Self, RM_FENGHAO, MakeWord(8, 0), 0, 0, 0, GetExtraLevelName);
              end;
              SendRefMsg(RM_FENGHAO, 64, m_wBianshenImg, m_wBianshenAppr, 0, '');
              Result := True;
            end;
        else begin
            Result := EatUseItems(StdItem.Shape);
            if not Result then Result := UseStdmodeFunItem(StdItem);
          end;
        end;
      end;
  end;
end;

function TPlayObject.EatUseItems(nShape: Integer): Boolean;                                         //004BD1BC
var
  Castle                                : TUserCastle;
begin
  Result := False;
  if m_boArrow and (nShape in [1..3, 5]) then Exit;
  case nShape of                                                                                    //
    1: begin
        SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
        BaseObjectMove(m_sHomeMap, '', '');
        Result := True;
      end;
    2: begin
        if not m_PEnvir.m_MapFlag.boNORANDOMMOVE then begin
          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
          BaseObjectMove(m_sMapName, '', '');
          Result := True;
        end;
      end;
    3: begin
        SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
        if PKLevel < 2 then begin
          BaseObjectMove(m_sHomeMap, IntToStr(m_nHomeX), IntToStr(m_nHomeY));
        end else begin
          BaseObjectMove(g_Config.sRedHomeMap, IntToStr(g_Config.nRedHomeX),
            IntToStr(g_Config.nRedHomeY));
        end;
        Result := True;
      end;
    4: begin
        if WeaptonMakeLuck() then Result := True;
      end;
    5: begin
        if m_MyGuild <> nil then begin
          if not m_boInFreePKArea then begin
            Castle := g_CastleManager.IsCastleMember(Self);
            {
            if UserCastle.IsMasterGuild(TGuild(m_MyGuild)) then begin
              BaseObjectMove(UserCastle.m_sHomeMap,IntToStr(UserCastle.GetHomeX),IntToStr(UserCastle.GetHomeY));
            }
            if (Castle <> nil) and Castle.IsMasterGuild(TGuild(m_MyGuild)) then begin
              BaseObjectMove(Castle.m_sHomeMap, IntToStr(Castle.GetHomeX),
                IntToStr(Castle.GetHomeY));
            end else begin
              SysMsg('无效', c_Red, t_Hint);
            end;
            Result := True;
          end else begin                                                                            //004BD3F7
            SysMsg('此处无法使用', c_Red, t_Hint);
          end;
        end;
      end;
    9: begin
        if RepairWeapon() then Result := True;
      end;
    10: begin
        if SuperRepairWeapon() then Result := True;
      end;
    11: begin
        if WinLottery() then Result := True;
      end;
  end;
end;

function TPlayObject.ExecuteScript(ScriptObj: TObject; sLabel: string): Boolean;
resourcestring
  sScriptExcept                         = '[Exception] TPlayObject::ExecuteScript %s';
begin
  Result := False;
  if ScriptObj <> nil then begin
    try
      m_nScriptGotoCount := 0;
      m_sScriptCurrLable := '';
      m_sScriptGoBackLable := '';
      Result := TNormNpc(ScriptObj).GotoLable(Self, sLabel, False);
    except
      MainOutMessage(Format(sScriptExcept, [sLabel]));
    end;
  end;
end;

function TPlayObject.FindViewHum(PlayObject: TObject): TPlayObject;
var
  i                                     : Integer;
begin
  Result := nil;
  try
    for i := 0 to m_VisibleHumanList.Count - 1 do
      if PlayObject = TObject(m_VisibleHumanList[i]) then begin
        Result := TPlayObject(m_VisibleHumanList[i]);
        Break;
      end;
  except

  end;
end;

//和组队玩家分配经验值

procedure TPlayObject.GainExp(dwExp: LongWord; dwMilitaryExp: LongWord; dwRepressDemonExp: LongWord);
var
  i, n, sumlv                           : Integer;
  PlayObject                            : TPlayObject;
  nCheckCode                            : Integer;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::GainExp(%s,checkcode=%d)';
const
  bonus                                 : array[0..GROUPMAX] of real = (1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2);
begin
  try
    nCheckCode := 0;
    if m_GroupOwner <> nil then begin                                                               //组队经验分配
      sumlv := 0;
      n := 0;
      nCheckCode := 1;
      for i := 0 to m_GroupOwner.m_GroupMembers.Count - 1 do begin
        PlayObject := TPlayObject(m_GroupOwner.m_GroupMembers.Objects[i]);
        nCheckCode := 2;
        if not PlayObject.m_boDeath and (m_PEnvir = PlayObject.m_PEnvir) and
          (abs(m_nCurrX - PlayObject.m_nCurrX) <= 12) and (abs(m_nCurrX -
          PlayObject.m_nCurrX) <= 12) then begin
          sumlv := sumlv + PlayObject.m_Abil.level;
          Inc(n);
        end;
      end;
      nCheckCode := 3;
      if (sumlv > 0) and (n > 1) then begin
        nCheckCode := 31;
        if n in [0..GROUPMAX] then begin
          dwExp := Round(dwExp * bonus[n]);
          dwMilitaryExp := Round(dwMilitaryExp * bonus[n]);
          dwRepressDemonExp := Round(dwRepressDemonExp * bonus[n]);
        end;
        for i := 0 to m_GroupOwner.m_GroupMembers.Count - 1 do begin
          PlayObject := TPlayObject(m_GroupOwner.m_GroupMembers.Objects[i]);
          if not PlayObject.m_boDeath and (m_PEnvir = PlayObject.m_PEnvir) and
            (abs(m_nCurrX - PlayObject.m_nCurrX) <= 12) and (abs(m_nCurrX -
            PlayObject.m_nCurrX) <= 12) then begin
            if g_Config.boHighLevelKillMonFixExp then begin                                         //02/08 增加,在高等级经验不变时,把组队的经验平均分配
              nCheckCode := 4;
              PlayObject.WinExp(Round(dwExp / n), dwMilitaryExp, dwRepressDemonExp);
              nCheckCode := 5;
              if (m_MyGuild <> nil) and (PlayObject.m_MyGuild <> nil) then begin
                if (TGuild(m_MyGuild).sGuildName = TGuild(PlayObject.m_MyGuild).sGuildName) then
                  TGuild(m_MyGuild).dwGuildExp := TGuild(m_MyGuild).dwGuildExp + Round(dwExp / n);  //05.06 增加组队行会经验
              end;
            end else begin
              nCheckCode := 6;
              PlayObject.WinExp(Round(dwExp / sumlv * PlayObject.m_Abil.level), dwMilitaryExp, dwRepressDemonExp);
              nCheckCode := 7;
              if (m_MyGuild <> nil) and (PlayObject.m_MyGuild <> nil) then begin
                if (TGuild(m_MyGuild).sGuildName = TGuild(PlayObject.m_MyGuild).sGuildName) then
                  TGuild(m_MyGuild).dwGuildExp := TGuild(m_MyGuild).dwGuildExp + Round(dwExp / sumlv * PlayObject.m_Abil.level); //05.06 增加组队行会经验
              end;
            end;
          end;
        end;
      end else WinExp(dwExp, dwMilitaryExp, dwRepressDemonExp);
    end else WinExp(dwExp, dwMilitaryExp, dwRepressDemonExp);
  except
    MainOutMessage(Format(sExceptionMsg, [m_sCharName, nCheckCode]));
  end;
end;

procedure TPlayObject.GameTimeChanged;
begin
  if m_nBright <> g_nGameTime then begin
    m_nBright := g_nGameTime;
    SendMsg(Self, RM_DAYCHANGING, 0, 0, 0, 0, '');
  end;
end;

//取回交易的物品

procedure TPlayObject.GetBackDealItems;                                                             //004DD270
var
  i                                     : Integer;
begin
  if m_DealItemList.Count > 0 then begin
    for i := 0 to m_DealItemList.Count - 1 do begin
      m_ItemList.Add(m_DealItemList.Items[i]);
    end;
  end;
  m_DealItemList.Clear;
  IncGold(m_nDealGolds);
  Inc(m_nGameGold, m_nDealGameGolds);
  m_nDealGolds := 0;
  m_nDealGameGolds := 0;
  m_boDealOK := False;
end;

procedure TPlayObject.GetBagUseItems(var btDc, btSc, btMc, btDura: byte);
var
  i, ii                                 : Integer;
  DuraList                              : TList;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  StdItem80                             : TStdItem;
  DelItemList                           : TStringList;
  nDc, nSc, nMc, nDcMin, nDcMax, nScMin, nScMax, nMcMin, nMcMax, nDura,
    nItemCount                          : Integer;
begin
  nDcMin := 0;
  nDcMax := 0;
  nScMin := 0;
  nScMax := 0;
  nMcMin := 0;
  nMcMax := 0;
  nDura := 0;
  nItemCount := 0;
  DelItemList := nil;
  DuraList := TList.Create;
  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];
    if UserEngine.GetStdItemName(UserItem.wIndex) = g_Config.sBlackStone then begin
      DuraList.Add(Pointer(Round(UserItem.Dura / 1.0E3)));
      if DelItemList = nil then DelItemList := TStringList.Create;
      DelItemList.AddObject(g_Config.sBlackStone, TObject(UserItem.MakeIndex));
      Dispose(UserItem);
      m_ItemList.Delete(i);
    end else begin
      if IsUseItem(UserItem.wIndex) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem <> nil then begin
          StdItem80 := StdItem^;
          ItemUnit.GetItemAddValue(UserItem, StdItem80);
          nDc := 0;
          nSc := 0;
          nMc := 0;
          case StdItem80.StdMode of
            19, 20, 21: begin                                                                       //004A0421
                nDc := HiWord(StdItem80.DC) + LoWord(StdItem80.DC);
                nSc := HiWord(StdItem80.SC) + LoWord(StdItem80.SC);
                nMc := HiWord(StdItem80.MC) + LoWord(StdItem80.MC);
              end;
            22, 23: begin                                                                           //004A046E
                nDc := HiWord(StdItem80.DC) + LoWord(StdItem80.DC);
                nSc := HiWord(StdItem80.SC) + LoWord(StdItem80.SC);
                nMc := HiWord(StdItem80.MC) + LoWord(StdItem80.MC);
              end;
            24, 26: begin
                nDc := HiWord(StdItem80.DC) + LoWord(StdItem80.DC) + 1;
                nSc := HiWord(StdItem80.SC) + LoWord(StdItem80.SC) + 1;
                nMc := HiWord(StdItem80.MC) + LoWord(StdItem80.MC) + 1;
              end;
          end;
          if nDcMin < nDc then begin
            nDcMax := nDcMin;
            nDcMin := nDc;
          end else begin
            if nDcMax < nDc then nDcMax := nDc;
          end;
          if nScMin < nSc then begin
            nScMax := nScMin;
            nScMin := nSc;
          end else begin
            if nScMax < nSc then nScMax := nSc;
          end;
          if nMcMin < nMc then begin
            nMcMax := nMcMin;
            nMcMin := nMc;
          end else begin
            if nMcMax < nMc then nMcMax := nMc;
          end;
          if DelItemList = nil then DelItemList := TStringList.Create;
          DelItemList.AddObject(StdItem.Name, TObject(UserItem.MakeIndex));
          //004A06DB
          if StdItem.boGameLog = 1 then
            AddGameDataLog('26' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(UserItem.MakeIndex) + #9 +
              '1' + #9 +
              '0');
          Dispose(UserItem);
          m_ItemList.Delete(i);
        end;
      end;
    end;
  end;                                                                                              // for
  for i := 0 to DuraList.Count - 1 do begin
    for ii := DuraList.Count - 1 downto i + 1 do begin
      if Integer(DuraList.Items[ii]) > Integer(DuraList.Items[ii - 1]) then
        DuraList.Exchange(ii, ii - 1);
    end;                                                                                            // for
  end;                                                                                              // for
  for i := 0 to DuraList.Count - 1 do begin
    nDura := nDura + Integer(DuraList.Items[i]);
    Inc(nItemCount);
    if nItemCount >= 5 then Break;
  end;
  btDura := Round(_MIN(5, nItemCount) + _MIN(5, nItemCount) * ((nDura /
    nItemCount) / 5.0));
  btDc := nDcMin div 5 + nDcMax div 3;
  btSc := nScMin div 5 + nScMax div 3;
  btMc := nMcMin div 5 + nMcMax div 3;
  if DelItemList <> nil then
    SendMsg(Self, RM_SENDDELITEMLIST, 0, Integer(DelItemList), 0, 0, '');

  if DuraList <> nil then DuraList.free;

end;

function TPlayObject.GeTBaseObjectInfo: string;
var
  perm                                  : Integer;
begin
  if m_btPermissionGM > 10 then perm := 0 else perm := m_btPermissionGM;
  Result := m_sCharName +
    ' 标识:' + IntToHex(Integer(Self), 2) +
    ' 权限等级: ' + IntToStr(perm) +
    ' 管理模式: ' + BoolToCStr(m_boAdminMode) +
    ' 隐身模式: ' + BoolToCStr(m_boObMode) +
    ' 无敌模式: ' + BoolToCStr(m_boSuperMan) +
    ' 地图:' + m_sMapName + '(' + m_PEnvir.m_sMapDesc + ')' +
    ' 座标:' + IntToStr(m_nCurrX) + ':' + IntToStr(m_nCurrY) +
    ' 等级:' + IntToStr(m_Abil.level) +
    ' 转生等级:' + IntToStr(m_btReLevel) +
    ' 经验:' + IntToStr(m_Abil.Exp) +
    ' 生命值: ' + IntToStr(m_WAbil.dwHP) + '-' + IntToStr(m_WAbil.dwMaxHP) +
    ' 魔法值: ' + IntToStr(m_WAbil.dwMP) + '-' + IntToStr(m_WAbil.dwMaxMP) +
    ' 攻击力: ' + IntToStr(loword(m_WAbil.DC)) + '-' +
    IntToStr(hiword(m_WAbil.DC)) +
    ' 魔法力: ' + IntToStr(loword(m_WAbil.MC)) + '-' +
    IntToStr(hiword(m_WAbil.MC)) +
    ' 道术: ' + IntToStr(loword(m_WAbil.SC)) + '-' +
    IntToStr(hiword(m_WAbil.SC)) +
    ' 防御力: ' + IntToStr(loword(m_WAbil.AC)) + '-' +
    IntToStr(hiword(m_WAbil.AC)) +
    ' 魔防力: ' + IntToStr(loword(m_WAbil.MAC)) + '-' +
    IntToStr(hiword(m_WAbil.MAC)) +
    ' 命中:' + IntToStr(m_dwHitPoint) +
    ' 躲避:' + IntToStr(m_dwSpeedPoint) +
    ' 速度:' + IntToStr(m_nHitSpeed) +
    ' 仓库密码:' + m_sStoragePwd +
    ' 登录IP:' + m_sIPaddr + '(' + m_sIPLocal {GetIPLocal(m_sIPaddr)} + ')' +
    ' 登录帐号:' + m_sUserID +
    ' 登录时间:' + DateToChStr(m_dLogonTime, True) +
    ' 在线时长(分钟):' + IntToStr((GetTickCount - m_dwLogonTick) div 60000)
    +
    ' 登录模式:' + IntToStr(m_nPayMent) +
    ' ' + g_Config.sGameGoldName + ':' + IntToStr(m_nGameGold) +
    ' ' + g_Config.sGamePointName + ':' + IntToStr(m_nGamePoint) +
    ' ' + g_Config.sPayMentPointName + ':' + IntToStr(m_nPayMentPoint) +
    ' 会员类型:' + IntToStr(m_nMemberType) +
    ' 会员等级:' + IntToStr(m_nMemberLevel) +
    ' 经验倍数:' + CurrToStr(m_nKillMonExpRate / 100) +
    ' 攻击倍数:' + CurrToStr(m_nPowerRate / 100) +
    ' 防御倍数:' + CurrToStr(m_nDefenceRate / 100) +
    ' 杀怪爆率:' + CurrToStr(m_nKillMonBurstRate / 100) +
    ' 声望值:' + IntToStr(m_wCreditPoint);
end;

//获取包裹中指定物品某属性的总和

function TPlayObject.GetItemValueSum(sItemName: string; sValName: string): Integer;
var
  UserItem                              : pTUserItem;
  i, nIdx, nValue                       : Integer;
  sValue                                : string;
begin
  Result := 0;
  nIdx := UserEngine.GetStdItemIdx(sItemName);
  if nIdx > 0 then begin
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];
      if UserItem.wIndex = nIdx then begin
        sValue := GetCheckItemValue(UserItem.MakeIndex, sValName);
        if sValue <> '' then begin
          nValue := Str_ToInt(sValue, 0);
          Inc(Result, nValue);
        end;
      end;
    end;
  end;
end;

//获取包裹中指定物品指定属性在一定数值以上的物品总数

function TPlayObject.GetItemCountWithValue(sItemName: string; sValName: string; nValue: Integer): Integer;
var
  UserItem                              : pTUserItem;
  i, nIdx, nPoint                       : Integer;
  sValue                                : string;
begin
  Result := 0;
  nIdx := UserEngine.GetStdItemIdx(sItemName);
  if nIdx > 0 then begin
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];
      if UserItem.wIndex = nIdx then begin
        sValue := GetCheckItemValue(UserItem.MakeIndex, sValName);
        if sValue <> '' then begin
          nPoint := Str_ToInt(sValue, 0);
          if nPoint >= nValue then Inc(Result);
        end;
      end;
    end;
  end;

end;

function TPlayObject.GetCheckItemValue(nMakeIndex: Integer; sName: string): string;
var
  UserItem                              : pTUserItem;
  i, p, n18                             : Integer;
  pStdItem, StdStone                    : pTStdItem;
  StdItem                               : TStdItem;
  s18, s19                              : string;
  boFind                                : Boolean;
  tm                                    : DWORD;
  nExp                                  : Int64;
  nSoulExp                              : UInt64;
  NPC                                   : TNormNpc;
begin
  Result := '';
  if (nMakeIndex = 0) then Exit;

  boFind := False;
  if (nMakeIndex >= 0) and (nMakeIndex <= High(THumItems)) then begin
    UserItem := @m_UseItems[nMakeIndex];
    if (UserItem.wIndex <> 0) then begin
      pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if pStdItem = nil then Exit;
      StdItem := pStdItem^;
      boFind := True;
    end;
  end else begin
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];
      if UserItem.MakeIndex = nMakeIndex then begin
        pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if pStdItem = nil then Exit;
        StdItem := pStdItem^;
        boFind := True;
        Break;
      end;
    end;

    if not boFind then for i := Low(THumItems) to High(THumItems) do begin
        UserItem := @m_UseItems[i];
        if (UserItem.wIndex <> 0) and (UserItem.MakeIndex = nMakeIndex) then begin
          pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if pStdItem = nil then Exit;
          StdItem := pStdItem^;
          boFind := True;
          Break;
        end;
      end;

    if not boFind then for i := Low(TTigerItems) to High(TTigerItems) do begin
        UserItem := @m_TorDDM.Tiger.Items[i];
        if (UserItem.wIndex <> 0) and (UserItem.MakeIndex = nMakeIndex) then begin
          pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if pStdItem = nil then Exit;
          StdItem := pStdItem^;
          boFind := True;
          Break;
        end;
      end;

  end;

  if boFind then begin
    ItemUnit.GetItemAddValue(UserItem, StdItem);

    if sName = 'MAKEINDEX' then Result := IntToStr(UserItem.MakeIndex)
    else if sName = 'IDX' then Result := IntToStr(UserItem.wIndex)
    else if sName = 'NAME' then Result := StdItem.FilterName
    else if sName = 'STDNAME' then Result := StdItem.Name
    else if sName = 'STDMODE' then Result := IntToStr(StdItem.StdMode)
    else if sName = 'SHAPE' then Result := IntToStr(StdItem.Shape)
    else if sName = 'WEIGHT' then Result := IntToStr(StdItem.Weight)
    else if sName = 'ANICOUNT' then Result := IntToStr(StdItem.AniCount)
    else if sName = 'SOURCE' then Result := IntToStr(StdItem.Source)
    else if sName = 'RESERVED' then Result := IntToStr(StdItem.Reserved)
    else if sName = 'NEEDAMBIT' then Result := IntToStr(StdItem.NeedAmbit)
    else if sName = 'LOOKS' then Result := IntToStr(StdItem.Looks)
    else if sName = 'DURAMAX' then Result := IntToStr(UserItem.DuraMax)
    else if sName = 'DURA' then Result := IntToStr(UserItem.Dura)
    else if sName = 'AC' then Result := IntToStr(StdItem.AC)
    else if sName = 'AC1' then Result := IntToStr(LoWord(StdItem.AC))
    else if sName = 'AC2' then Result := IntToStr(HiWord(StdItem.AC))
    else if sName = 'MAC' then Result := IntToStr(StdItem.MAC)
    else if sName = 'MAC1' then Result := IntToStr(LoWord(StdItem.MAC))
    else if sName = 'MAC2' then Result := IntToStr(HiWord(StdItem.MAC))
    else if sName = 'DC' then Result := IntToStr(StdItem.DC)
    else if sName = 'DC1' then Result := IntToStr(LoWord(StdItem.DC))
    else if sName = 'DC2' then Result := IntToStr(HiWord(StdItem.DC))
    else if sName = 'MC' then Result := IntToStr(StdItem.MC)
    else if sName = 'MC1' then Result := IntToStr(LoWord(StdItem.MC))
    else if sName = 'MC2' then Result := IntToStr(HiWord(StdItem.MC))
    else if sName = 'SC' then Result := IntToStr(StdItem.SC)
    else if sName = 'SC1' then Result := IntToStr(LoWord(StdItem.SC))
    else if sName = 'SC2' then Result := IntToStr(HiWord(StdItem.SC))
    else if sName = 'GC1' then Result := IntToStr(LoWord(StdItem.GC))
    else if sName = 'GC2' then Result := IntToStr(HiWord(StdItem.GC))
    else if sName = 'NEED' then Result := IntToStr(StdItem.Need)
    else if sName = 'NEEDLEVEL' then Result := IntToStr(StdItem.NeedLevel)
    else if sName = 'FEATURE' then Result := IntToStr(StdItem.Feature)
    else if sName = 'NEEDRACE' then Result := IntToStr(StdItem.NeedRace)
    else if sName = 'THUMP' then Result := IntToStr(StdItem.StdItemAdd.btThump)
    else if sName = 'THUMP2' then Result := IntToStr(StdItem.StdItemAdd.btThump2)
    else if sName = 'MAGICNICETY' then Result := IntToStr(StdItem.StdItemAdd.btMagicNicety)
    else if sName = 'HEROIC' then Result := IntToStr(StdItem.StdItemAdd.wHeroic)
    else if sName = 'MAXHOLE' then Result := IntToStr(StdItem.StdItemAdd.btHole)
    else if sName = 'PRICE' then Result := IntToStr(StdItem.Price)
    else if sName = 'STOCK' then Result := IntToStr(StdItem.Stock)
    else if sName = 'CLIAN1ATTRIB' then Result := IntToStr(StdItem.StdItemAdd.btCLianAttrib[0])
    else if sName = 'CLIAN1VAL' then Result := IntToStr(StdItem.StdItemAdd.dwCLianVal[0])
    else if sName = 'CLIAN1VAL1' then Result := IntToStr(LoWord(StdItem.StdItemAdd.dwCLianVal[0]))
    else if sName = 'CLIAN1VAL2' then Result := IntToStr(HiWord(StdItem.StdItemAdd.dwCLianVal[0]))
    else if sName = 'CLIAN1EXP' then Result := IntToStr(StdItem.StdItemAdd.dwCLianExp[0])
    else if sName = 'CLIAN2ATTRIB' then Result := IntToStr(StdItem.StdItemAdd.btCLianAttrib[1])
    else if sName = 'CLIAN2VAL' then Result := IntToStr(StdItem.StdItemAdd.dwCLianVal[1])
    else if sName = 'CLIAN2VAL1' then Result := IntToStr(LoWord(StdItem.StdItemAdd.dwCLianVal[1]))
    else if sName = 'CLIAN2VAL2' then Result := IntToStr(HiWord(StdItem.StdItemAdd.dwCLianVal[1]))
    else if sName = 'CLIAN2EXP' then Result := IntToStr(StdItem.StdItemAdd.dwCLianExp[1])
    else if sName = 'CLIAN3ATTRIB' then Result := IntToStr(StdItem.StdItemAdd.btCLianAttrib[2])
    else if sName = 'CLIAN3VAL' then Result := IntToStr(StdItem.StdItemAdd.dwCLianVal[2])
    else if sName = 'CLIAN3VAL1' then Result := IntToStr(LoWord(StdItem.StdItemAdd.dwCLianVal[2]))
    else if sName = 'CLIAN3VAL2' then Result := IntToStr(HiWord(StdItem.StdItemAdd.dwCLianVal[2]))
    else if sName = 'CLIAN3EXP' then Result := IntToStr(StdItem.StdItemAdd.dwCLianExp[2])
    else if sName = 'SEAL' then Result := IntToStr(_Lo(UserItem.btValue[13]))
    else if sName = 'LONGLEVEL' then Result := IntToStr(UserItem.btItemExt[16] + 1)
    else if sName = 'LONGCUREXP' then Result := UInt64ToStr(PUInt64(@UserItem.btItemExt[18])^)
    else if sName = 'LONGALLEXP' then begin
      nExp := PUInt64(@UserItem.btItemExt[18])^;
      i := _MIN(UserItem.btItemExt[16], 200);
      while i > 0 do begin
        Dec(i);
        Inc(nExp, g_Config.LongLevelUpExp[i]);
      end;
      Result := UInt64ToStr(nExp);
    end else if Pos('VALUE', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if (p in [0..19]) then
        Result := IntToStr(UserItem.btValue[p])
      else
        Result := '0';
    end else if Pos('CUSTOM', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if (p in [100..119]) then
        Result := IntToStr(UserItem.btExtra.btCustomValue[p - 100])
      else
        Result := '0';
    end else if Pos('ITEMEXTEX', sName) = 1 then begin
      if Pos('ITEMEXTEX(', sName) = 1 then
        ArrestStringEx(sName, '(', ')', s18)
      else
        ArrestStringEx(sName, '[', ']', s18);
      if g_FunctionNPC = nil then Exit;
      s18 := g_FunctionNPC.GetPlayObjectInfo(TPlayObject(Self), s18);
      p := Str_ToInt(s18, -1);
      case p of
        0..9: Result := IntToStr(UserItem.btExtra.Shield.sEx[p]);
        147..148: Result := IntToStr(UserItem.btExtra.Shield.sEx[p - 137]);
      end;
    end else if Pos('ITEMEXT', sName) = 1 then begin
      if Pos('ITEMEXT(', sName) = 1 then
        ArrestStringEx(sName, '(', ')', s18)
      else
        ArrestStringEx(sName, '[', ']', s18);
      if g_FunctionNPC = nil then Exit;
      s18 := g_FunctionNPC.GetPlayObjectInfo(TPlayObject(Self), s18);
      p := Str_ToInt(s18, -1);
      case p of
        21: Result := IntToStr(UserItem.DuraMax);
        22: Result := IntToStr(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]));
        23..38: Result := IntToStr(_Hi(UserItem.btItemExt[p - 23]));
        39..54: Result := IntToStr(_Lo(UserItem.btItemExt[p - 39]));
        55..70: Result := IntToStr(UserItem.btItemExt[p - 55]);
        71: Result := IntToStr(MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3])));
        72: Result := IntToStr(MakeLong(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]), MakeWord(UserItem.btItemExt[2], UserItem.btItemExt[3])));
        73..79: Result := '0';
        80..92: Result := IntToStr(UserItem.btItemExt[p - 64]);
        100: Result := IntToStr(UserItem.btItemExt[p - 71]);
        101: Result := IntToStr(MakeLong(MakeWord(UserItem.btItemExt2[146], UserItem.btItemExt2[147]), MakeWord(UserItem.btItemExt2[148], UserItem.btItemExt2[149])));
        120..149: Result := IntToStr(UserItem.btItemExt[p - 88]);
        169: Result := IntToStr(PWORD(@UserItem.btItemExt[26])^);
        170: Result := IntToStr(PDWORD(@UserItem.btItemExt[24])^);
        216: Result := IntToStr(UserItem.btExtra.Shield.dwHP);
        217..218: Result := IntToStr(UserItem.btExtra.Shield.btValue[p - 217]);
        219: Result := IntToStr(UserItem.btExtra.Shield.wStrengHP);
        220: Result := IntToStr(UserItem.btExtra.Shield.wStrengDC);
        221: Result := IntToStr(UserItem.btExtra.Shield.wStrengAC);
        222: Result := IntToStr(UserItem.btExtra.Shield.wStrengMAC);
        223: Result := IntToStr(UserItem.btExtra.Shield.wAwaken);
        224: Result := IntToStr(UserItem.btExtra.Shield.btValue[p - 221]);
        225: Result := IntToStr(UserItem.btExtra.Shield.wAwakenVal1);
        226: Result := IntToStr(UserItem.btExtra.Shield.wAwakenVal2);
        227..228: Result := IntToStr(UserItem.btExtra.Shield.btValue[p - 223]);
        229: Result := IntToStr(UserItem.btExtra.Shield.wDivineVal1);
        230: Result := IntToStr(UserItem.btExtra.Shield.wDivineVal2);
        231: Result := IntToStr(UserItem.btExtra.Shield.wNowExp);
        232: Result := IntToStr(UserItem.btExtra.Shield.wMaxExp);
        233: Result := IntToStr(UserItem.btExtra.Shield.nStrengGold);
        234: Result := IntToStr(UserItem.btExtra.Shield.wStrengMaterial);
        235: Result := IntToStr(UserItem.btExtra.Shield.nAwakenGold);
        236: Result := IntToStr(UserItem.btExtra.Shield.wAwakenMaterial);
        237: Result := IntToStr(UserItem.GetItemPunch(1));
        238: Result := IntToStr(UserItem.GetItemPunch(2));
        239: Result := IntToStr(UserItem.GetItemPunch(3));
        240: Result := IntToStr(UserItem.btItemExt2[21]);
        241: Result := IntToStr(UserItem.btExtra.Spirit[0].btLevel);
        242: Result := IntToStr(UserItem.btExtra.Spirit[0].btPosition);
        243: Result := IntToStr(UserItem.btExtra.Spirit[0].nValue1);
        244: Result := IntToStr(UserItem.btExtra.Spirit[0].nValue2);
        245: Result := IntToStr(UserItem.btExtra.Spirit[1].btLevel);
        246: Result := IntToStr(UserItem.btExtra.Spirit[1].btPosition);
        247: Result := IntToStr(UserItem.btExtra.Spirit[1].nValue1);
        248: Result := IntToStr(UserItem.btExtra.Spirit[1].nValue2);
        249: Result := IntToStr(UserItem.btExtra.Shield.wVampirePoint);
        250: Result := IntToStr(PDWORD(@UserItem.btItemExt2[0])^);
        251: Result := IntToStr(PDWORD(@UserItem.btItemExt2[4])^);
        252: Result := IntToStr(PDWORD(@UserItem.btItemExt2[8])^);
        253: Result := IntToStr(PDWORD(@UserItem.btItemExt2[12])^);
        254: Result := IntToStr(PDWORD(@UserItem.btItemExt2[16])^);
        255: Result := IntToStr(PDWORD(@UserItem.btItemExt2[20])^);
        256: Result := IntToStr(PDWORD(@UserItem.btItemExt2[24])^);
        257: Result := IntToStr(PDWORD(@UserItem.btItemExt2[58])^);
        258: Result := IntToStr(PDWORD(@UserItem.btItemExt2[62])^);
        267: Result := IntToStr(PDWORD(@UserItem.btItemExt[29])^);
        268: begin
            SetLength(s18, 15);
            Move(UserItem^.btItemExt2[28], PChar(s18)^, 15);
            Result := s18;
          end;
        269: begin
            SetLength(s18, 15);
            Move(UserItem^.btItemExt2[43], PChar(s18)^, 15);
            Result := s18;
          end;
        270: begin
            SetLength(s18, 15);
            Move(UserItem^.btItemExt2[66], PChar(s18)^, 15);
            Result := s18;
          end;
        271: begin
            SetLength(s18, 15);
            Move(UserItem^.btItemExt2[81], PChar(s18)^, 15);
            Result := s18;
          end;
        274: Result := IntToStr(MakeLong(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]), MakeWord(UserItem.btItemExt[2], UserItem.btItemExt[3])));
        275: Result := IntToStr(MakeLong(MakeWord(UserItem.btItemExt[4], UserItem.btItemExt[5]), MakeWord(UserItem.btItemExt[6], UserItem.btItemExt[7])));

      end;
    end else if sName = 'GLOOMPOINT' then
      Result := IntToStr(MakeWord(UserItem.btItemExt[0], UserItem.btItemExt[1]))

    else if Pos('LOGLOOM', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if (p in [0..16]) then
        Result := IntToStr(_Hi(UserItem.btItemExt[p]))
      else
        Result := '0';
    end else if Pos('HIGLOOM', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if (p in [0..16]) then
        Result := IntToStr(_Lo(UserItem.btItemExt[p]))
      else
        Result := '0';
    end else if sName = 'OVERLAP' then
      Result := IntToStr(MakeLong(MakeWord(UserItem.btValue[0],
        UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3])))
    else if Pos('EVIL', sName) = 1 then begin
      if UserItem.Evil.MakeIndex = 0 then Result := ''
      else if sName = 'EVILNAME' then
        Result := UserItem.Evil.sName
      else if sName = 'EVILJOB' then
        Result := IntToJob(UserItem.Evil.btJob)
      else if sName = 'EVILAMBIT' then
        Result := IntToStr(UserItem.Evil.btAmbit)
      else if sName = 'EVILDC' then
        Result := IntToStr(LoByte(UserItem.Evil.wDC))
      else if sName = 'EVILDC2' then
        Result := IntToStr(HiByte(UserItem.Evil.wDC))
      else if sName = 'EVILMC' then
        Result := IntToStr(LoByte(UserItem.Evil.wMC))
      else if sName = 'EVILMC2' then
        Result := IntToStr(HiByte(UserItem.Evil.wMC))
      else if sName = 'EVILSC' then
        Result := IntToStr(LoByte(UserItem.Evil.wSC))
      else if sName = 'EVILSC2' then
        Result := IntToStr(HiByte(UserItem.Evil.wSC))
      else if sName = 'EVILAC' then
        Result := IntToStr(LoByte(UserItem.Evil.wDC))
      else if sName = 'EVILAC2' then
        Result := IntToStr(HiByte(UserItem.Evil.wDC))
      else if sName = 'EVILMAC' then
        Result := IntToStr(LoByte(UserItem.Evil.wMC))
      else if sName = 'EVILMAC2' then
        Result := IntToStr(HiByte(UserItem.Evil.wMC))
      else if sName = 'EVILPOWER' then
        Result := IntToStr(UserItem.Evil.wPower)
    end else if Pos('PET.', sName) = 1 then begin                                                   //灵兽石属性
      if sName = 'PET.NAME' then
        Result := UserItem.sExName
      else if sName = 'PET.TYPE' then
        Result := IntToStr(UserItem.btValue[8])
      else if sName = 'PET.KIND' then Result := IntToStr(StdItem.AniCount)
      else if sName = 'PET.LEVEL' then
        Result := IntToStr(UserItem.wLevel)
      else if sName = 'PET.TYPENAME' then begin
        case UserItem.btValue[8] of
          0: Result := '小灵兽';
          1: Result := '灵兽1';
          2: Result := '灵兽2';
          3: Result := '灵兽3';
        else
          Result := '灵兽(未知)';
        end;
      end
      else if sName = 'PET.EXP' then
        Result := IntToStr(UserItem.dwExp)
      else if sName = 'PET.MAXEXP' then begin
        Result := IntToStr(GetPetUpExp(UserItem.btValue[9], UserItem.wLevel));
      end
      else if sName = 'PET.STATE' then begin
        tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        if tm = 0 then tm := DateTimeToWolTIme(Now);
        n18 := DateTimeToWolTIme(Now) - tm;
        n18 := n18 div 86400;
        if n18 <= 2 then Result := '饱'
        else if n18 = 3 then Result := '微饿'
        else if n18 = 4 then Result := '饥饿'
        else Result := '死亡';
      end
      else if sName = 'PET.EATTIME' then begin
        tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
        if tm = 0 then tm := DateTimeToWolTIme(Now);
        Result := IntToStr((DateTimeToWolTIme(Now) - tm) div 3600);
      end else if sName = 'PET.RELIVE' then
        Result := IntToStr(UserItem.btValue[9])
      else if sName = 'PET.PILEEXP' then
        Result := IntToStr(UserItem.dwTotalExp)
      else if sName = 'PET.EVOLUTION' then
        Result := IntToStr(UserItem.wEvoluTion)
      else if sName = 'PET.APTITUDE' then
        Result := IntToStr(UserItem.btAptiTude)
      else if sName = 'PET.HP' then
        Result := IntToStr(UserItem.wHP)
      else if sName = 'PET.MP' then
        Result := IntToStr(UserItem.wMP)
      else if sName = 'PET.ANTIPOISON' then
        Result := IntToStr(UserItem.btAntiPoison)
      else if sName = 'PET.MAC1' then
        Result := IntToStr(LoByte(UserItem.wMAC))
      else if sName = 'PET.MAC2' then
        Result := IntToStr(HiByte(UserItem.wMAC))
      else if sName = 'PET.MAGICNICETY' then
        Result := IntToStr(UserItem.btMagicNicety)
      else if sName = 'PET.EVADET' then
        Result := IntToStr(UserItem.btEvaDet)
      else if sName = 'PET.AC1' then
        Result := IntToStr(LoByte(UserItem.wAC))
      else if sName = 'PET.AC2' then
        Result := IntToStr(HiByte(UserItem.wAC))
      else if sName = 'PET.ANTIMAGIC' then
        Result := IntToStr(UserItem.btAntiMagic)
      else if sName = 'PET.POISONNICETY' then
        Result := IntToStr(UserItem.btPoisonNicety)
      else if sName = 'PET.SAVVY' then
        Result := IntToStr(UserItem.btSavvy)
      else if sName = 'PET.FELEMENT1' then begin
        case UserItem.btFelemEntType[0] of
          0: Result := '金';
          1: Result := '木';
          2: Result := '土';
          3: Result := '水';
        end;
      end else if sName = 'PET.FELEMENT2' then begin
        case UserItem.btFelemEntType[1] of
          0: Result := '火';
          1: Result := '木';
          2: Result := '土';
          3: Result := '水';
        end;
      end else if sName = 'PET.FELEMENTPOINT1' then
        Result := IntToStr(UserItem.btFelemEntPoint[0])
      else if sName = 'PET.FELEMENTPOINT2' then
        Result := IntToStr(UserItem.btFelemEntPoint[1])
      else if sName = 'PET.MC1' then
        Result := IntToStr(LoByte(UserItem.wMC))
      else if sName = 'PET.MC2' then
        Result := IntToStr(HiByte(UserItem.wMC))
      else if sName = 'PET.SC1' then
        Result := IntToStr(LoByte(UserItem.wSC))
      else if sName = 'PET.SC2' then
        Result := IntToStr(HiByte(UserItem.wSC))
      else if sName = 'PET.DC1' then
        Result := IntToStr(LoByte(UserItem.wDC))
      else if sName = 'PET.DC2' then
        Result := IntToStr(HiByte(UserItem.wDC))
      else if sName = 'PET.NICETY' then
        Result := IntToStr(UserItem.btHitNicety)
      else if sName = 'PET.LUCK' then
        Result := IntToStr(UserItem.btLuck)
      else if sName = 'PET.SPEED' then
        Result := IntToStr(UserItem.btRideSpeed)
      else if sName = 'PET.GENDER' then
        Result := IntToStr(UserItem.btItemExt[25])                                                  //性别
      else if sName = 'PET.PARALY' then
        Result := IntToStr(UserItem.btItemExt[16])
      else if sName = 'PET.THUMP' then
        Result := IntToStr(UserItem.btItemExt[17])
      else if sName = 'PET.AGAINST' then
        Result := IntToStr(MakeWord(UserItem.btItemExt[18], UserItem.btItemExt[19]))
      else if sName = 'PET.REDUCEAC' then
        Result := IntToStr(UserItem.btItemExt[20])
      else if sName = 'PET.REDUCEMAC' then
        Result := IntToStr(UserItem.btItemExt[21])
      else if sName = 'PET.REDUCEHITPOINT' then
        Result := IntToStr(UserItem.btItemExt[22])
      else if sName = 'PET.REDUCEANTIMAGIC' then
        Result := IntToStr(UserItem.btItemExt[23])
      else if sName = 'PET.SIRE' then
        Result := IntToStr(UserItem.btItemExt[26])
      else if sName = 'PET.SIREMAX' then
        Result := IntToStr(UserItem.btItemExt[27])
      else if sName = 'PET.BLOODPURE' then
        Result := IntToStr(UserItem.btItemExt[28])
      else if sName = 'PET.STRENG' then
        Result := IntToStr(UserItem.btItemExt[30])
      else if sName = 'PET.INSIGHTLEVEL' then
        Result := IntToStr(UserItem.btExtra.btLevel)
      else if sName = 'PET.QUALIFICATION' then
        Result := IntToStr(UserItem.btExtra.btInsight)
      else if sName = 'PET.INSIGHTEXP' then
        Result := IntToStr(UserItem.btExtra.nExp)
      else if sName = 'PET.INSIGHTMAXEXP' then
        Result := IntToStr(UserItem.btExtra.nMaxExp)
      else if sName = 'PET.NEXTQUALIFICATION' then
        Result := IntToStr(UserItem.btExtra.btNext)
      else if sName = 'PET.INSIGHTMAGICID(0)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[0].GetID)
      else if sName = 'PET.INSIGHTMAGICID(1)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[1].GetID)
      else if sName = 'PET.INSIGHTMAGICID(2)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[2].GetID)
      else if sName = 'PET.INSIGHTMAGICID(3)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[3].GetID)
      else if sName = 'PET.INSIGHTMAGICLEVEL(0)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[0].GetLv)
      else if sName = 'PET.INSIGHTMAGICLEVEL(1)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[1].GetLv)
      else if sName = 'PET.INSIGHTMAGICLEVEL(2)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[2].GetLv)
      else if sName = 'PET.INSIGHTMAGICLEVEL(3)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[3].GetLv)
      else if sName = 'PET.INSIGHTMAGICVALUE(0)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[0].GetValue)
      else if sName = 'PET.INSIGHTMAGICVALUE(1)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[1].GetValue)
      else if sName = 'PET.INSIGHTMAGICVALUE(2)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[2].GetValue)
      else if sName = 'PET.INSIGHTMAGICVALUE(3)' then
        Result := IntToStr(UserItem.btExtra.PetSkill[3].GetValue)
      else
        Result := '';
    end else if Pos('OFFICERVALUE', sName) = 1 then begin                                           //仙官装备属性
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if (p in [0..3]) then
        Result := IntToStr(PWORD(@UserItem.btValue[p * 2])^)
      else
        Result := '0';
    end else if Pos('GODITEM.', sName) = 1 then begin                                               //神兵装备属性
      if sName = 'GODITEM.NAME' then
        Result := UserItem.God_Nmae
      else if sName = 'GODITEM.HUMNAME' then
        Result := UserItem.God_MainNmae
      else if sName = 'GODITEM.MINDC' then
        Result := IntToStr(UserItem.God_MinDC)
      else if sName = 'GODITEM.MAXDC' then
        Result := IntToStr(UserItem.God_MaxDC)
      else if sName = 'GODITEM.REDUCEAC' then
        Result := IntToStr(UserItem.God_ReduceAC)
      else if sName = 'GODITEM.REDUCEMAC' then
        Result := IntToStr(UserItem.God_ReduceMAC)
      else if sName = 'GODITEM.USEVAL' then
        Result := IntToStr(UserItem.God_UseVal)
      else if sName = 'GODITEM.JOB' then
        Result := IntToStr(UserItem.God_Job)
      else if sName = 'GODITEM.RULER' then
        Result := IntToStr(UserItem.God_Ruler)
      else if sName = 'GODITEM.GOD' then
        Result := IntToStr(Integer(UserItem.IsGod))
      else if sName = 'GODITEM.SUITE' then begin
        if StdItem.StdMode = 5 then begin
          Result := IntToStr(UserItem.btItemExt[24])
        end else if StdItem.StdMode in [10, 11] then begin
          Result := IntToStr(UserItem.btItemExt[20])
        end;
      end else
        Result := '';
    end else if Pos('GEM', sName) = 1 then begin                                                    //装备镶嵌玉石的属性
      Result := '0';
      //s19 := ArrestStringEx(sName, '[', ']', s18);
      if CheckBrackets(sName, s18) then begin
        s19 := Copy(sName, Length('GEM().') + Length(s18) + 1, Length(sName));
        if g_FunctionNPC <> nil then
          s18 := g_FunctionNPC.GetPlayObjectInfo(Self, s18);
        p := Str_ToInt(s18, -1);
        if p in [1..5] then begin
          Dec(p);
          if s19 = 'HOLE' then begin
            tm := UserItem.btItemExt[18 + (p * 2)] and $0F;
            if tm in [0..1] then begin
              if p = 0 then
                Result := '1'
              else
                Result := IntToStr(tm);
            end else if tm = 3 then
              Result := '2'
            else if tm = 7 then
              Result := '3';
          end else if s19 = 'LV' then
            Result := IntToStr(UserItem.btItemExt[18 + (p * 2)] shr 4)
          else if s19 = 'MAG' then
            Result := IntToStr(UserItem.btItemExt[18 + (p * 2) + 1])
          else
            Result := '';
        end;
      end;
    end else if Pos('JEWEL', sName) = 1 then begin                                                  //装备镶嵌玉石的属性
      if CheckBrackets(sName, s18) then begin
        s19 := Copy(sName, Length('JEWEL().') + Length(s18) + 1, Length(sName));
        if g_FunctionNPC <> nil then
          s18 := g_FunctionNPC.GetPlayObjectInfo(Self, s18);
        p := Str_ToInt(s18, -1);
        if p in [1..3] then begin
          if s19 = 'SHAPE' then
            Result := '0'
          else if s19 = 'NAME' then Result := '';
          if UserItem.GetItemPunch(p) = 0 then Exit;
          StdStone := UserEngine.GetStdItem(UserItem.btExtra.ItemIndex[p - 1]);
          if (StdStone = nil) or (StdStone.StdMode <> 141) then Exit;
          if s19 = 'SHAPE' then
            Result := IntToStr(StdStone^.Shape)
          else if s19 = 'NAME' then
            Result := StdStone^.Name;
        end;
      end;
    end else if Pos('HOLECOUNT', sName) = 1 then begin                                              //装备镶嵌玉石的属性
      p := 1;
      for i := 0 to 4 do
        if UserItem.btItemExt[18 + (p * 2)] > 0 then
          Inc(p);
      Result := IntToStr(p);
    end else if Pos('GOODITEMTYPE', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if p in [1..3] then begin
        case p of
          1: Result := IntToStr(UserItem.btItemExt[20] div 16);
          2: Result := IntToStr(UserItem.btItemExt[30] div 16);
          3: Result := IntToStr(UserItem.btItemExt[31] div 16);
        end;
      end;
    end else if Pos('GOODITEMVALUE', sName) = 1 then begin
      ArrestStringEx(sName, '(', ')', s18);
      p := Str_ToInt(s18, -1);
      if p in [1..3] then begin
        case p of
          1: begin
              n18 := UserItem.btItemExt[20] div 16;
              Result := IntToStr(UserItem.btItemExt[20] - (n18 * 16));
            end;
          2: begin
              n18 := UserItem.btItemExt[30] div 16;
              Result := IntToStr(UserItem.btItemExt[30] - (n18 * 16));
            end;
          3: begin
              n18 := UserItem.btItemExt[31] div 16;
              Result := IntToStr(UserItem.btItemExt[31] - (n18 * 16));
            end;
        end;
      end;
    end else if Pos('SOULBEAD', sName) = 1 then begin
      if sName = 'SOULBEADLEVEL' then begin
        Result := IntToStr(UserItem.btValue[12]);
      end else if sName = 'SOULBEADHP' then begin
        Result := IntToStr(PWORD(@UserItem.btValue[6])^);
      end else if sName = 'SOULBEADCUREXP' then begin
        Result := UInt64ToStr(PINT64(@UserItem.btItemExt[44])^);
      end else if sName = 'SOULBEADMAXEXP' then begin
        if StdItem.AniCount = 0 then
          nSoulExp := g_Config.SoulBead0[StdItem.Price]
        else
          nSoulExp := g_Config.SoulBead1[StdItem.Price];
        Result := UInt64ToStr(nSoulExp);
      end;
    end else if sName = 'CUSTOMNAME' then begin
      ItemUnit.GetCustomItemName(UserItem, s19);
      Result := s19;
    end;
  end;
end;

function TPlayObject.GetDigUpMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_BUTCH) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

function TPlayObject.GetExploit(PlayObject: TBaseObject): Boolean;
var
  nMaxExp                               : integer;
  btLevel                               : Byte;
begin
  Result := False;
  btLevel := PlayObject.m_MilitaryInfo.nLevel;
  nMaxExp := g_Config.MilitaryRank[btLevel].nNextLevelExp;
  if (PlayObject.m_MilitaryInfo.nExp >= nMaxExp) then begin
    Result := True;
    while True do begin
      btLevel := PlayObject.m_MilitaryInfo.nLevel;
      nMaxExp := g_Config.MilitaryRank[btLevel].nNextLevelExp;
      if (PlayObject.m_MilitaryInfo.nExp >= nMaxExp) and (nMaxExp > 0) and (btLevel < 81) then begin
        if (btLevel mod 9 <> 0) or (g_Config.MilitaryRank[btLevel].boAutoLevelUp) then begin
          Dec(PlayObject.m_MilitaryInfo.nExp, nMaxExp);
          Inc(PlayObject.m_MilitaryInfo.nLevel);
        end;
      end else
        Break;
    end;
  end;
end;

function TPlayObject.GetWingExp(): Boolean;
var
  nMaxExp                               : integer;
  btLevel                               : Byte;
begin
  Result := False;
  btLevel := m_HumWingInfo.nLevel;
  nMaxExp := g_Config.RepressDemonWings.LevelData[btLevel].NextLevelExp;
  if (m_HumWingInfo.nExp >= nMaxExp) then begin
    Result := True;
    while True do begin
      btLevel := m_HumWingInfo.nLevel;
      nMaxExp := g_Config.RepressDemonWings.LevelData[btLevel].NextLevelExp;
      if (m_HumWingInfo.nExp >= nMaxExp) and (nMaxExp > 0) and (btLevel < 50) then begin
        if g_Config.RepressDemonWings.LevelData[btLevel].AutoLevelUp then begin
          Dec(m_HumWingInfo.nExp, nMaxExp);
          Inc(m_HumWingInfo.nLevel);
        end else begin
          m_HumWingInfo.nExp := nMaxExp;
          Break;
        end;
      end else
        Break;
    end;
  end;

  if m_HumWingInfo.btWear > 99 then
    m_HumWingInfo.btWingLook := m_HumWingInfo.btWear
  else
    m_HumWingInfo.btWingLook := g_Config.RepressDemonWings.LevelData[m_HumWingInfo.nLevel].Wing_Look;
end;

function TPlayObject.GetBeadExp(): Boolean;
var
  nMaxExp                               : integer;
  btLevel                               : Byte;
begin
  Result := False;
  btLevel := m_RepressDemon.nLevel;
  nMaxExp := g_Config.RepressDemon[btLevel].nNextLevelExp;
  if (m_RepressDemon.nExp >= nMaxExp) then begin
    Result := True;
    while True do begin
      btLevel := m_RepressDemon.nLevel;
      nMaxExp := g_Config.RepressDemon[btLevel].nNextLevelExp;
      if (m_RepressDemon.nExp >= nMaxExp) and (nMaxExp > 0) and (btLevel < 60) then begin
        Dec(m_RepressDemon.nExp, nMaxExp);
        Inc(m_RepressDemon.nLevel);
      end else
        Break;
    end;
  end;
end;

//人物经验值增长

procedure TPlayObject.GetExp(nExp: UInt64; nMilitaryExp: UInt64; nRepressDemon: UInt64; bScritpExp: Boolean = False; boShareMilitaryExp: Boolean = False; boShareRepressDemon: Boolean = False);
var
  nShareExp1, nShareExp2, nShareExp3    : UInt64;
begin
  nShareExp1 := 0;
  nShareExp2 := 0;
  nShareExp3 := 0;
  if m_boPneuma then begin                                                                          //是元神
    if m_PneumaObject <> nil then begin                                                             //元神主人 <> nil
      nShareExp1 := _Max(0, nExp div 3);
      if (not boShareMilitaryExp) and (bScritpExp) then                                             //判断脚本是否分享给元神
        nShareExp2 := nMilitaryExp
      else
        nShareExp2 := _Max(0, nMilitaryExp div 3);                                                  //判断脚本是否分享给元神
      if (not boShareRepressDemon) and (bScritpExp) or ((m_PneumaObject as TPlayObject).m_RepressDemon.nLevel = 0) then
        nShareExp3 := nRepressDemon
      else
        nShareExp3 := _Max(0, nRepressDemon div 3);

      GetExpProc(nShareExp1, nShareExp2, nShareExp3, bScritpExp);                                   //元神 1/3
      (m_PneumaObject as TPlayObject).GetExpProc(_Max(0, nExp - nShareExp1), _MAX(0, nMilitaryExp - nShareExp2), _MAX(0, nRepressDemon - nShareExp3), bScritpExp);
      //主任 2/3
    end;
  end else begin                                                                                    //是人物
    if (m_btJob = 3) then
      nExp := GetYaoDanShareExp(nExp);

    if (m_PneumaObject <> nil) and (not m_boPneumaEffMode) then begin                               //元神在线
      nShareExp1 := _Max(0, nExp div 3);
      nShareExp2 := _Max(0, nMilitaryExp div 3);
      if ((m_PneumaObject as TPlayObject).m_RepressDemon.nLevel > 0) and (boShareRepressDemon) then
        nShareExp3 := _Max(0, nRepressDemon div 3);
      nExp := _Max(0, nExp - nShareExp1);
      nMilitaryExp := _Max(0, nMilitaryExp - nShareExp2);
      if ((m_PneumaObject as TPlayObject).m_RepressDemon.nLevel > 0) and (boShareRepressDemon) then
        nRepressDemon := _Max(0, nRepressDemon - nShareExp3);
      (m_PneumaObject as TPlayObject).GetExpProc(nShareExp1, nShareExp2, nShareExp3, bScritpExp);
      GetExpProc(nExp, nMilitaryExp, nRepressDemon, bScritpExp);
    end else                                                                                        //元神不在线或没元神
      GetExpProc(nExp, nMilitaryExp, nRepressDemon, bScritpExp);
  end;
end;

procedure TPlayObject.GetExpProc(nGetExp: UInt64; nGetMilitaryExp: UInt64; nGetRepressDemonExp: UInt64; bScritpExp: Boolean = False);
var
  n14, nCode, nType                     : Integer;
  nInt                                  : UInt64;
  nSoulExp, nNewSoulExp, nSoulMaxExp    : UInt64;
  nMaxExp, nAccrued                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  boRecalc, boLevelUp                   : Boolean;
  RefExpPacket                          : TRefExpPacket;
  boReachMaxLevel                       : Boolean;
  boReachLevelLimitExp                  : Boolean;
resourcestring
  sSoulExpMsg                           = '在%s的作用下,额外增加了%d经验';
  sTimeBackExpMsg                       = '%s增加%d点经验(穿戴真魂珠后,主体不增加经验)';
begin
  if m_PEnvir = nil then Exit;

  //检测是否到达最高等级,限制等级后经验槽达100%满
  if (g_Config.nLimitLevel = m_Abil.level) and ((m_Abil.Exp + nGetExp) >= m_Abil.MaxExp) then begin
    if m_Abil.Exp < m_Abil.MaxExp then begin
      //向客户端发送经验
      RefExpPacket.nExp := m_Abil.Exp;
      RefExpPacket.nInc := m_Abil.MaxExp - m_Abil.Exp;
      SendMsg(Self, RM_WINEXP, 0, m_Abil.MaxExp - m_Abil.Exp, 0, 0, EnCodeBuffer(@RefExpPacket, SizeOf(TRefExpPacket)));
      m_Abil.Exp := m_Abil.MaxExp;
    end;
    Exit;
  end;

  //功勋值触发
  if (nGetMilitaryExp > 0) and (g_Config.boMagicCityServer) and (m_MilitaryInfo.nLevel > 0) then begin
    Inc(m_MilitaryInfo.nExp, nGetMilitaryExp);
    m_sScriptParam[23] := UInt64ToStr(nGetMilitaryExp);
    m_sScriptParam[24] := BoolToIntStr(bScritpExp);
    m_sScriptParam[25] := BoolToIntStr(GetExploit(TBaseObject(Self)));
    ExecuteScript(g_ManageNPC, '@GetMilitaryExpFucn');
    SysMsg(Format('%d功勋值增加', [nGetMilitaryExp]), c_Red, t_Hint);
  end;

  //镇魔珠经验触发
{$IF DEMONSERVER = 1}
  if (nGetRepressDemonExp > 0) and (m_RepressDemon.nLevel > 0) then begin
    Inc(m_RepressDemon.nExp, nGetRepressDemonExp);
    m_sScriptParam[23] := UInt64ToStr(nGetRepressDemonExp);
    m_sScriptParam[24] := BoolToIntStr(bScritpExp);
    m_sScriptParam[25] := BoolToIntStr(GetBeadExp());
    ExecuteScript(g_ManageNPC, '@GetRepressDemonExpFucn');
    SysMsg(Format('镇魔珠增加%d经验', [nGetRepressDemonExp]), c_Red, t_Hint);
  end;
{$IFEND}
  if nGetExp = 0 then Exit;

  if (not bScritpExp) then begin
    UserItem := @m_UseItems[U_SOULBEAD];                                                            //魂珠
    if (UserItem.wIndex > 0) and (UserItem.btValue[11] = 0) and (UserItem.btValue[15] > 0) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        nSoulExp := (nGetExp * UserItem.btValue[15]) div 100;                                       //整除
        if (nSoulExp > 0) then begin
          Inc(nGetExp, nSoulExp);
          SysMsg(Format(sSoulExpMsg, [StdItem.FilterName, nSoulExp]), c_Red, t_Hint);
        end;
      end;
    end;
  end;

  if (not g_Config.boClassicServer) then                                                            //Script 2016.07.01 时光区魂珠
  begin
    if {(not bScritpExp) and }(nGetExp > 0) then begin
      UserItem := @m_UseItems[U_SOULBEAD];
      if (UserItem.wIndex > 0) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem.StdMode = 99 then begin
          if StdItem.AniCount = 0 then
            nSoulMaxExp := g_Config.SoulBead0[UserItem.btValue[12]]
          else
            nSoulMaxExp := g_Config.SoulBead1[UserItem.btValue[12]];
          if (nGetExp > 0) then begin
            if g_Config.boWearSoulBeadPlayerExp then
            begin
              nSoulExp := PINT64(@UserItem.btItemExt[44])^;
              nNewSoulExp := nGetExp + nSoulExp;
              if nNewSoulExp >= nSoulMaxExp then begin
                nGetExp := _MAX(0, nNewSoulExp - nSoulMaxExp);
                nSoulExp := nSoulMaxExp;
                PINT64(@UserItem.btItemExt[44])^ := nSoulExp;
              end else begin
                nSoulExp := nGetExp;
                nGetExp := 0;
                PINT64(@UserItem.btItemExt[44])^ := PINT64(@UserItem.btItemExt[44])^ + nSoulExp;
                SysMsg(Format(sTimeBackExpMsg, [StdItem.FilterName, nSoulExp]), c_Red, t_Hint);
              end;
              SendUpdateItem(UserItem);
              if (nGetExp < 1) then Exit;
            end else begin
              nSoulExp := PINT64(@UserItem.btItemExt[44])^;
              nNewSoulExp := nGetExp + nSoulExp;
              if nNewSoulExp >= nSoulMaxExp then begin
                PINT64(@UserItem.btItemExt[44])^ := nSoulExp;
              end else begin
                PINT64(@UserItem.btItemExt[44])^ := PINT64(@UserItem.btItemExt[44])^ + nGetExp;
              end;
              SendUpdateItem(UserItem);
            end;
          end;
        end;
      end
    end;
  end;

  boLevelUp := False;

  //检查是否达到最高等级
  boReachMaxLevel := False;
  if g_Config.boHighLevelLimitExp then begin
    if m_btAmbitKind in [7, 8] then begin                                                           //上仙 以是最高级
      if (m_btAmbitLevel >= g_Config.nHighAmbitLevelLimit3) then begin
        boReachMaxLevel := True;
      end;
    end;
  end else begin
    if (m_Abil.level >= g_Config.nLimitLevel) then begin
      boReachMaxLevel := True;
    end;
  end;
  boReachLevelLimitExp := (boReachMaxLevel) and (m_Abil.Exp >= m_Abil.MaxExp);

  m_sScriptParam[20] := UInt64ToStr(nGetExp);
  m_sScriptParam[21] := BoolToIntStr(bScritpExp);
  m_sScriptParam[22] := BoolToIntStr(boReachLevelLimitExp);
  ExecuteScript(g_ManageNPC, '@GetExpFucn');
  if UInt64ToStr(nGetExp) <> m_sScriptParam[20] then nGetExp := Str_ToInt(m_sScriptParam[20], 0);

  if (not m_boPneuma) then begin
    SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 0, 0, 0, '', 200);
  end else begin
    SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 1, 0, 0, '', 200);
  end;

  //龙纹钢吸取经验
  if (not m_boPneuma) and (nGetExp > 0) then begin
    if boReachLevelLimitExp then
      nGetExp := nGetExp * 2;

    if (m_nGatherExp + nGetExp) > MAX_ULONG64 then
      nInt := MAX_ULONG64 - m_nGatherExp
    else
      nInt := nGetExp;
    Inc(m_nGatherExp, nInt);
  end;

  if boReachLevelLimitExp then nGetExp := 1;

  if (not bScritpExp) and m_PEnvir.m_MapFlag.boLayupExp then begin
    n14 := m_PEnvir.m_MapFlag.nLayupExp;
    if (n14 >= 300) and (n14 <= 399) then begin
      Dec(n14, 300);
      if (m_nMval[n14] + nGetExp) > MAX_ULONG64 then
        nInt := MAX_ULONG64 - m_nMval[n14]
      else
        nInt := nGetExp;
      m_nMval[n14] := m_nMval[n14] + nInt;
    end;
  end else begin
    Inc(m_Abil.Exp, nGetExp);

    if not boReachMaxLevel then begin
      boRecalc := False;
      if m_Abil.Exp >= m_Abil.MaxExp then begin
        Dec(m_Abil.Exp, m_Abil.MaxExp);
        if g_Config.boHighLevelLimitExp then begin
          //升级增加天人重数
          if m_btAmbitKind > 2 then begin
            boRecalc := True;
            boLevelUp := True;
            case m_btAmbitKind of
              3, 4: begin                                                                           //天人
                  if (m_btAmbitLevel < g_Config.nHighAmbitLevelLimit1) then begin
                    Inc(m_btAmbitLevel);
                  end else if g_Config.boAutoUpAmbitKind2 then begin
                    Inc(m_btAmbitKind, 2);
                    m_btAmbitLevel := 1;
                  end;
                end;
              5, 6: begin                                                                           //天仙
                  if (m_btAmbitLevel < g_Config.nHighAmbitLevelLimit2) then begin
                    Inc(m_btAmbitLevel);
                  end else if g_Config.boAutoUpAmbitKind3 then begin
                    Inc(m_btAmbitKind, 2);
                    m_btAmbitLevel := 1;
                  end;
                end;
              7, 8: begin                                                                           //上仙
                  if (m_btAmbitLevel < g_Config.nHighAmbitLevelLimit3) then begin
                    Inc(m_btAmbitLevel);
                  end else begin
                    boLevelUp := False;
                  end;
                end;
            end;
          end;
          //等级同时提升
          if m_Abil.level < g_Config.nLimitLevel then begin
            Inc(m_Abil.level);
            boLevelUp := True;
          end;

          if g_Config.boAutoUpAmbitKind1 and (m_Abil.level >= g_Config.nAutoUpAmbitLevel) and (m_btAmbitKind < 3) then begin
            if Random(10) < 5 then m_btAmbitKind := 3 else m_btAmbitKind := 4;
            m_btAmbitLevel := (m_Abil.level - g_Config.nAutoUpAmbitLevel) + 1;
            boRecalc := True;
            boLevelUp := True;
          end;
        end else begin
          if m_Abil.level < MAXUPLEVEL then begin
            Inc(m_Abil.level);
            boLevelUp := True;
          end;
        end;

        if boLevelUp then begin
          HasLevelUp(m_Abil.level - 1);
          AddBodyLuck(100);
          IncHealthSpell(2000, 2000);
          m_WAbil.wElementForce := m_WAbil.wElementForceMax;
          AddGameDataLog('12' + #9 +
            m_sMapName + #9 +
            IntToStr(m_Abil.level) + #9 +
            IntToStr(m_Abil.Exp) + #9 +
            m_sCharName + #9 +
            '0' + #9 +
            '0' + #9 +
            '1' + #9 +
            '0');
        //  m_BattleVal.nMinVal[0] := m_Abil.Level;
          m_BattleVal.BattleVal := m_BattleVal.nMinVal[0] + m_BattleVal.nMinVal[1] +
            m_BattleVal.nMinVal[2] + m_BattleVal.nMinVal[3] + m_BattleVal.nMinVal[4];
          SendDefMessage(SM_BATTLEVAL, Integer(Self), m_BattleVal.BattleVal, 0, 0,
            EnCodeBuffer(@m_BattleVal, SizeOf(TBattleData)), True);

          nCode := 0;
          nType := 0;
          if not g_Config.boClassicServer then begin                                                //修为系统

            if g_Config.boClientRedPacket then
              nCode := nCode + 32;
            if g_Config.boClientPreferential then
              nType := 8;
            if g_Config.boClientBackUserExp then
              nType := nType + 1;
            SendDefMessage(SM_816, nType, 0, MakeWord(15, nCode), 0, '');
          end else begin
            SendDefMessage(SM_816, 0, 1, 15, 0, '');
          end;

          if (m_PEnvir.m_MapFlag.sLevelUpGotoLabel <> '') then
            ExecuteScript(g_ManageNPC, m_PEnvir.m_MapFlag.sLevelUpGotoLabel);
          ExecuteScript(g_FunctionNPC, '@升级触发');
        end;
        if boRecalc then begin
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
          FeatureChanged;
        end;
      end;
    end;

    //向客户端发送经验
    RefExpPacket.nExp := m_Abil.Exp;
    RefExpPacket.nInc := nGetExp;
    AddBodyLuck(nGetExp * 0.002);
    SendMsg(Self, RM_WINEXP, 0, nGetExp, 0, 0, EnCodeBuffer(@RefExpPacket, SizeOf(TRefExpPacket)));
  end;
end;

function TPlayObject.GetHitMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_HIT) or
        (SendMessage.wIdent = CM_HEAVYHIT) or
        (SendMessage.wIdent = CM_BIGHIT) or
        (SendMessage.wIdent = CM_POWERHIT) or
        (SendMessage.wIdent = CM_LONGHIT) or
        (SendMessage.wIdent = CM_WIDEHIT) or
        (SendMessage.wIdent = CM_FIREHIT) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

function TPlayObject.GetMyInfo: string;
var
  sMyInfo                               : string;
begin
  sMyInfo := g_sMyInfo;
  sMyInfo := AnsiReplaceText(sMyInfo, '%name', m_sCharName);
  sMyInfo := AnsiReplaceText(sMyInfo, '%map', m_PEnvir.m_sMapDesc);
  sMyInfo := AnsiReplaceText(sMyInfo, '%x', IntToStr(m_nCurrX));
  sMyInfo := AnsiReplaceText(sMyInfo, '%y', IntToStr(m_nCurrY));
  sMyInfo := AnsiReplaceText(sMyInfo, '%level', IntToStr(m_Abil.level));
  sMyInfo := AnsiReplaceText(sMyInfo, '%gold', IntToStr(m_nGold));
  sMyInfo := AnsiReplaceText(sMyInfo, '%pk', IntToStr(m_nPkPoint));
  sMyInfo := AnsiReplaceText(sMyInfo, '%minhp', IntToStr(m_WAbil.dwHP));
  sMyInfo := AnsiReplaceText(sMyInfo, '%maxhp', IntToStr(m_WAbil.dwMaxHP));
  sMyInfo := AnsiReplaceText(sMyInfo, '%minmp', IntToStr(m_WAbil.dwMP));
  sMyInfo := AnsiReplaceText(sMyInfo, '%maxmp', IntToStr(m_WAbil.dwMaxMP));
  sMyInfo := AnsiReplaceText(sMyInfo, '%mindc', IntToStr(loword(m_WAbil.DC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%maxdc', IntToStr(hiword(m_WAbil.DC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%minmc', IntToStr(loword(m_WAbil.MC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%maxmc', IntToStr(hiword(m_WAbil.MC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%minsc', IntToStr(loword(m_WAbil.SC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%maxsc', IntToStr(hiword(m_WAbil.SC)));
  sMyInfo := AnsiReplaceText(sMyInfo, '%logontime',
    DateToChStr(m_dLogonTime, True));
  sMyInfo := AnsiReplaceText(sMyInfo, '%logonlong', IntToStr((GetTickCount -
    m_dwLogonTick) div 60000));
  Result := sMyInfo;
end;

function TPlayObject.GetMyStatus: Integer;                                                          //708
begin
  Result := m_nHungerStatus div 1000;                                                               //饥饿点
  if Result > 4 then Result := 4;
end;

//获得当前人物所在地图位置的玩家数

function TPlayObject.GetRangeHumanCount: Integer;
begin
  Result := UserEngine.GetMapOfRangeHumanCount(m_PEnvir, m_nCurrX, m_nCurrY, 10);
end;

function TPlayObject.GetRunMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_RUN) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

//取得当前脚本可以跳转的标签

procedure TPlayObject.GetScriptLabel(sMsg: string; boLeft: Boolean);
var
  sText                                 : string;
  sData                                 : string;
  sCmdStr, sLabel                       : string;
  i                                     : Integer;
begin
  if boLeft then
    m_CanJmpScriptLableList2.Clear
  else
    m_CanJmpScriptLableList.Clear;
  while (True) do begin
    if sMsg = '' then Break;
    sMsg := GetValidStr3(sMsg, sText, ['\']);
    if sText <> '' then begin
      sData := '';
      while (sText <> '') and (Pos('<', sText) > 0) and (Pos('>', sText) > 0) do begin              //0419
        if sText[1] <> '<' then begin
          sText := '<' + GetValidStr3(sText, sData, ['<']);
        end;
        sText := ArrestStringEx(sText, '<', '>', sCmdStr);
        if (sCmdStr <> '') and (TagCount(sCmdStr, '/') >= 1) then begin
          //sLabel := GetValidStr3(sCmdStr, sCmdStr, ['/']);
          i := 1;
          GetToken(sCmdStr, '/', i);
          sLabel := GetToken(sCmdStr, '/', i);
          if sLabel <> '' then begin
            if boLeft then
              m_CanJmpScriptLableList2.Add(sLabel)
            else
              m_CanJmpScriptLableList.Add(sLabel);
          end;
        end;
      end;
    end;
  end;
end;

function TPlayObject.GetShowName: string;
var
  i                                     : Integer;
  sShowName                             : string;
  sCharName                             : string;
  sGuildName                            : string;
  sDearName                             : string;
  sMasterName                           : string;
  Castle                                : TUserCastle;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::GetShowName';
  sIsYS                                 = '的元神)';
begin
  try
    sCharName := '';
    sGuildName := '';
    sDearName := '';
    sMasterName := '';
    if m_MyGuild <> nil then begin
      Castle := g_CastleManager.IsCastleMember(Self);
      if (m_wPersonalCode and 4 = 0) then begin
        if (Castle <> nil) then begin
          sGuildName := AnsiReplaceText(g_sCastleGuildName, '%castlename', Castle.m_sName);
          sGuildName := AnsiReplaceText(sGuildName, '%guildname', TGuild(m_MyGuild).sGuildName);
          sGuildName := AnsiReplaceText(sGuildName, '%rankname', m_sGuildRankName);
        end else begin
          Castle := g_CastleManager.InCastleWarArea(Self);
          if g_Config.boShowGuildName or (((Castle <> nil) and Castle.m_boUnderWar) or m_boInFreePKArea) then begin
            sGuildName := AnsiReplaceText(g_sNoCastleGuildName, '%guildname', TGuild(m_MyGuild).sGuildName);
            sGuildName := AnsiReplaceText(sGuildName, '%rankname', m_sGuildRankName);
          end;
        end;
      end;
    end;

    if not g_Config.boShowRankLevelName then begin
      if m_btReLevel > 0 then begin
        case m_btJob of
          0: sCharName := AnsiReplaceText(g_sWarrReNewName, '%chrname', m_sCharName);
          1: sCharName := AnsiReplaceText(g_sWizardReNewName, '%chrname', m_sCharName);
          2: sCharName := AnsiReplaceText(g_sTaosReNewName, '%chrname', m_sCharName);
          3: sCharName := AnsiReplaceText(g_sGoblinReNewName, '%chrname', m_sCharName);
        end;
      end else begin
        sCharName := m_sCharName;
      end;
    end else begin
      sCharName := Format(m_sRankLevelName, [m_sCharName]);
    end;

{$IF COUNTRYSYSTEM = 1}
    if not m_boPneuma and (m_btCountry > 0) and (m_sOffName <> '') then begin                       //官职名称,元神不给予官职
      if GetCountryInfo(m_btCountry).sKing = m_sCharName then
        sCharName := sCharName + '\[' + GetCountryInfo(m_btCountry).sName + '-国王]'
      else
        sCharName := sCharName + '\[' + GetCountryInfo(m_btCountry).sName + '-' + m_sOffName + ']';
    end;
{$IFEND}

    if m_boMaster and g_Config.boShowPrenticeName then begin
      for i := 1 to 3 do begin
        if m_sMasterName[i] <> '' then begin
          sMasterName := sMasterName + '\' + Format(g_sMasterName, [m_sMasterName[i]]);
          Break;
        end;
      end;
    end else if (m_sMasterName[1] <> '') and (g_Config.boShowMasterName) then begin
      sMasterName := Format(g_sNoMasterName, [m_sMasterName[1]]);
    end;

    if (m_wPersonalCode and 1 = 0) then begin
      if m_sDearName <> '' then begin
        if m_btGender = 0 then begin
          sDearName := Format(g_sManDearName, [m_sDearName]);
        end else begin
          sDearName := Format(g_sWoManDearName, [m_sDearName]);
        end;
      end;
    end;

    sShowName := AnsiReplaceText(g_sHumanShowName, '%chrname', sCharName);

    if (g_Config.boShowPrenticeName and m_boMaster) or (g_Config.boShowMasterName and not m_boMaster) then
      sShowName := AnsiReplaceText(sShowName, '%mastername', sMasterName + '\')
    else
      sShowName := AnsiReplaceText(sShowName, '%mastername', '');

    if (sGuildName <> '') and (not m_boPneuma) then
      sShowName := AnsiReplaceText(sShowName, '%guildname\', sGuildName + '\')
    else
      sShowName := AnsiReplaceText(sShowName, '%guildname\', '');

    if sDearName <> '' then
      sShowName := AnsiReplaceText(sShowName, '%dearname\', sDearName + '\')
    else
      sShowName := AnsiReplaceText(sShowName, '%dearname\', '');
    {
     if m_wAttachePoint > 100 then
       sShowName := sShowName + '[' + m_sAttacheName + ']';
     }
    if m_boPneuma and (m_PneumaObject <> nil) then begin
      sShowName := sShowName + '\(' + m_PneumaObject.m_sCharName + sIsYS
    end;

    if (m_wPersonalCode and 32 = 0) then begin
      if Length(m_sTmpRank) > 0 then sShowName := sShowName + '\' + m_sTmpRank;
    end;

    //关灯模式
    if (m_PEnvir.m_MapFlag.boSECRET and ((m_PEnvir.m_MapFlag.btSECRETRule and SECRET_RULE_UNITENAME) <> 0)) then
    begin
      sShowName := g_ManageNPC.GetLineVariableText(self, m_PEnvir.m_MapFlag.sSECRETCHRNAME);
    end;

    //神秘人
    if m_boSecretMode and (m_sSecretName <> '') then begin
      sShowName := m_sSecretName;
    end;
    Result := sShowName;
  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg);
    end;
  end;
end;

function TPlayObject.GetSiteDownMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  EnterCriticalSection(ProcessMsgCriticalSection);
  try
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_SITDOWN) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

function TPlayObject.GetSpellMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_SPELL) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

//获得出生点

procedure TPlayObject.GetStartPoint;
var
  i                                     : Integer;
  SP                                    : pTStartPointInfo;
begin
  if m_boPneuma and (m_PneumaObject <> nil) then begin
    m_sHomeMap := m_PneumaObject.m_sHomeMap;
    m_nHomeX := TPlayObject(m_PneumaObject).m_nHomeX;
    m_nHomeY := TPlayObject(m_PneumaObject).m_nHomeY;
    Exit;
  end;
  if PKLevel >= 2 then begin
    m_sHomeMap := g_Config.sRedHomeMap;                                                             //红名地图
    m_nHomeX := g_Config.nRedHomeX;
    m_nHomeY := g_Config.nRedHomeY;
  end else begin
    for i := 0 to m_CurSafeZoneList.Count - 1 do begin
      SP := m_CurSafeZoneList[i];
      if (SP.Envir = m_PEnvir) and (abs(m_nCurrX - SP.X) < 50) and (abs(m_nCurrY - SP.Y) < 50) then begin
        m_sHomeMap := SP.sMapName;
        m_nHomeX := SP.X;
        m_nHomeY := SP.Y;
        Break;
      end;
    end;
  end;
end;

function TPlayObject.GetColorTaskCount(): Integer;
var
  i                                     : Integer;
  pTask                                 : PTTask;
  wColor                                : word;
begin
  Result := 0;
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    wColor := HiWord(pTask^.Step);
    if (HiByte(wColor) = 2) then Inc(Result);
  end;
end;

function TPlayObject.GetTaskStep(const TaskID: Integer): Integer;
var
  i                                     : Integer;
  pTask                                 : PTTask;
begin
  Result := 0;
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      Result := LoWord(pTask^.Step);
      Break;
    end;
  end;
end;

function TPlayObject.GetTaskStr(const TaskID: Integer; ValID: Integer): string;
var
  i                                     : Integer;
  pTask                                 : PTTask;
begin
  Result := '';
  if (ValID < 0) or (ValID >= MAX_TASK_S_VAL_COUNT) then Exit;
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      Result := pTask^.sVal[ValID];
      Break;
    end;
  end;
end;

function TPlayObject.GetTaskVal(const TaskID: Integer; ValID: Integer): Integer;
var
  i                                     : Integer;
  pTask                                 : PTTask;
begin
  Result := -1;
  if (ValID < 0) or (ValID >= MAX_TASK_I_VAL_COUNT) then Exit;
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      Result := pTask^.nVal[ValID];
      Break;
    end;
  end;
end;

{获取宝箱转盘物品??}

procedure TPlayObject.GetTreasureBoxItem(wParam: word; nParam1, nParam2,
  nParam3: Integer; sMsg: string);
var
  i, n                                  : Integer;
  BlessItems                            : TBlessTreeItem;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
begin
  m_nRandomGiveStep := nParam2;
  case nParam2 of
    {自动开宝箱关闭}
    7: begin
        m_nRandomGiveStep := 0;
        m_nAutoOpenTreasureBox := MakeWord(0, HiByte(m_nAutoOpenTreasureBox));
        Exit;
      end;
    {打开祈愿树}
    12: begin
        m_BLESSNPC := m_ClickNPC;
      end;
    {放上祈愿符}
    268: begin
        m_sScriptParam[0] := '0';
        DeCodeBuffer(sMsg, @n, SizeOf(Integer));
        m_sScriptParam[1] := IntToStr(MakeLong(nParam3, wParam));
        m_sScriptParam[2] := IntToStr(n);
        if m_BLESSNPC <> nil then
          TNormNpc(m_BLESSNPC).GotoLable(Self, '@StartBless', False);
      end;
    {开始祈愿}
    524: begin
        GetUserItemByMakeIndex(MakeLong(nParam3, wParam), UserItem);
        if UserItem <> nil then begin
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if StdItem <> nil then begin
            BlessItems.Name := StdItem.FilterName;
            BlessItems.Looks := StdItem.Looks;

            m_defMsg := MakeDefaultMsg(SM_627, Integer(Self), 1036, 1, 0);
            SendSocket(@m_defMsg, EnCodeBuffer(@BlessItems, SizeOf(TBlessTreeItem)));
          end;
        end;

        DeCodeBuffer(sMsg, @n, SizeOf(Integer));
        m_sScriptParam[0] := '1';
        m_sScriptParam[1] := IntToStr(MakeLong(nParam3, wParam));
        m_sScriptParam[2] := IntToStr(n);
        if m_BLESSNPC <> nil then
          TNormNpc(m_BLESSNPC).GotoLable(Self, '@StartBless', False);
      end;
    {自动开宝箱开启}
    263: begin
        m_nAutoOpenTreasureBox := MakeWord(1, HiByte(m_nAutoOpenTreasureBox));
        Exit;
      end;
    {显示物品}
    264, 520, 776, 1032: begin
        if m_sNextLabel <> '' then begin
          m_sScriptParam[0] := IntToStr(nParam2 div 256);
          m_sScriptParam[10] := '0';
          if m_SMELTNPC <> nil then
            TNormNpc(m_SMELTNPC).GotoLable(Self, m_sNextLabel, False);
        end;
      end;
    {自动开启宝箱}
    265, 521, 777, 1033: begin
        if m_SMELTNPC <> nil then begin
          m_sScriptParam[0] := IntToStr(HiByte(m_nAutoOpenTreasureBox)
            {宝箱类型});
          TNormNpc(m_SMELTNPC).GotoLable(Self, '@OpenBox', False);
        end;
        SendDefMessage(627, Integer(Self), nParam2 + 252, 4, 0, '');
        Exit;
      end;
    {获取物品}
    266, 522, 778, 1034: begin
        m_sScriptParam[0] := IntToStr(nParam2 div 256);
        m_sScriptParam[10] := '1';
        if m_sNextLabel <> '' then begin
          if m_SMELTNPC <> nil then
            TNormNpc(m_SMELTNPC).GotoLable(Self, m_sNextLabel, False);
        end;
      end;
    {关闭宝箱,重新洗牌}
    267, 523, 779, 1035: begin
        for i := 0 to 10 do m_sScriptParam[i] := '0';
        m_sNextLabel := '';
        m_SMELTNPC := nil;
        m_nAutoOpenTreasureBox := $00;
        SendDefMessage(627, Integer(Self), 0, 0, 0, '');
      end;
  end;
end;

function TPlayObject.GetTurnMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_TURN) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

function TPlayObject.GetWalkMsgCount: Integer;
var
  i                                     : Integer;
  SendMessage                           : pTSendMessage;
begin
  Result := 0;
  try
    EnterCriticalSection(ProcessMsgCriticalSection);
    for i := 0 to m_MsgList.Count - 1 do begin
      SendMessage := m_MsgList.Items[i];
      if (SendMessage.wIdent = CM_WALK) then begin
        Inc(Result);
      end;
    end;
  finally
    LeaveCriticalSection(ProcessMsgCriticalSection);
  end;
end;

procedure TPlayObject.GoldChange(sChrName: string; nGold: Integer);
resourcestring
  sMsg                                  = '% 的金币%d 金币%s';
var
  s10, s14                              : string;
begin
  if nGold > 0 then begin
    s10 := '14';
    s14 := '增加完成';
  end else begin
    s10 := '13';
    s14 := '以删减';
  end;
  SysMsg(Format(sMsg, [sChrName, nGold, s14]), c_Green, t_Hint);

  if g_boGameLogGold then
    AddGameDataLog(s10 + #9 +
      m_sMapName + #9 +
      IntToStr(m_nCurrX) + #9 +
      IntToStr(m_nCurrY) + #9 +
      m_sCharName + #9 +
      sSTRING_GOLDNAME + #9 +
      IntToStr(nGold) + #9 +
      '1' + #9 +
      sChrName);
end;

function TPlayObject.HorseRunTo(btDir: byte; boFlag: Boolean): Boolean;
const
  nRunStep                              = 3;
var
  nOldX, nOldY                          : Integer;
  btRideFightSpeed                      : byte;
  boHumanRun                            : Boolean;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::HorseRunTo';
begin
  Result := False;
  if (m_btGodRunTime > 0) then begin
    btRideFightSpeed := 3;
  end else if m_boPneuma and (m_PneumaObject <> nil) then begin
    btRideFightSpeed := TPlayObject(m_PneumaObject).m_PetInfo[3].btRideFightSpeed;
  end else begin
    btRideFightSpeed := m_PetInfo[2].btRideFightSpeed;
  end;
  if m_boRideOn and m_boRideFightOn and (btRideFightSpeed = 0) then Exit;

  boHumanRun := g_Config.boDiableHumanRun or ((m_btPermissionGM > 9) and g_Config.boGMRunAll) or (g_Config.boSafeZoneRunAll and InSafeZone);
  try
    nOldX := m_nCurrX;
    nOldY := m_nCurrY;
    m_btDirection := btDir;
    case btDir of
      DR_UP {0}: begin
          if m_boFlyer or (m_nCurrY > 2) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY - 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY - 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY - 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX, m_nCurrY - 3, True) > 0) then begin

            Dec(m_nCurrY, nRunStep);
          end;
        end;
      DR_UPRIGHT {1}: begin
          if m_boFlyer or (m_nCurrX < m_PEnvir.m_nWidth - 3) and
            (m_nCurrY > 2) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 1, m_nCurrY - 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 2, m_nCurrY - 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 3, m_nCurrY - 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX + 3, m_nCurrY - 3, True) > 0) then begin

            Inc(m_nCurrX, nRunStep);
            Dec(m_nCurrY, nRunStep);
          end;
        end;
      DR_RIGHT {2}: begin
          if m_boFlyer or (m_nCurrX < m_PEnvir.m_nWidth - 3) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 1, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 2, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 3, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX + 3, m_nCurrY, True) > 0) then begin

            Inc(m_nCurrX, nRunStep);
          end;
        end;
      DR_DOWNRIGHT {3}: begin
          if m_boFlyer or (m_nCurrX < m_PEnvir.m_nWidth - 3) and
            (m_nCurrY < m_PEnvir.m_nHeight - 3) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 1, m_nCurrY + 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 2, m_nCurrY + 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX + 3, m_nCurrY + 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX + 3, m_nCurrY + 3, True) > 0) then begin

            Inc(m_nCurrX, nRunStep);
            Inc(m_nCurrY, nRunStep);
          end;
        end;
      DR_DOWN {4}: begin
          if m_boFlyer or (m_nCurrY < m_PEnvir.m_nHeight - 3) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY + 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY + 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX, m_nCurrY + 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX, m_nCurrY + 3, True) > 0) then begin

            Inc(m_nCurrY, nRunStep);
          end;
        end;
      DR_DOWNLEFT {5}: begin
          if m_boFlyer or (m_nCurrX > 2) and
            (m_nCurrY < m_PEnvir.m_nHeight - 3) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 1, m_nCurrY + 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 2, m_nCurrY + 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 3, m_nCurrY + 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX - 3, m_nCurrY + 3, True) > 0) then begin

            Dec(m_nCurrX, nRunStep);
            Inc(m_nCurrY, nRunStep);
          end;
        end;
      DR_LEFT {6}: begin
          if m_boFlyer or (m_nCurrX > 2) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 1, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 2, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 3, m_nCurrY, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX - 3, m_nCurrY, True) > 0) then begin

            Dec(m_nCurrX, nRunStep);
          end;
        end;
      DR_UPLEFT {7}: begin
          if m_boFlyer or (m_nCurrX > 2) and
            (m_nCurrY > 2) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 1, m_nCurrY - 1, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 2, m_nCurrY - 2, boHumanRun {True})) and
            (m_PEnvir.CanWalkEx(m_nCurrX - 3, m_nCurrY - 3, boHumanRun {True})) and
            (m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, m_nCurrX - 3, m_nCurrY - 3, True) > 0) then begin

            Dec(m_nCurrX, nRunStep);
            Dec(m_nCurrY, nRunStep);
          end;
        end;
    end;
    if (m_nCurrX <> nOldX) or (m_nCurrY <> nOldY) then begin
      if Walk(RM_RUN) then Result := True
      else begin
        if m_boFlyer or (m_PEnvir.MoveToMovingObject(nOldX, nOldY, Self, m_nCurrX, m_nCurrY, True) > 0) then begin
          m_nCurrX := nOldX;
          m_nCurrY := nOldY;
        end;
      end;
    end;
  except
    MainOutMessage(sExceptionMsg);
  end;
end;

//指定玩家是否在被阻止私聊列表中

function TPlayObject.IsBlockWhisper(sName: string): Boolean;
var
  i                                     : Integer;
begin
  Result := False;
  for i := 0 to m_BlockWhisperList.Count - 1 do begin
    if CompareText(sName, m_BlockWhisperList.Strings[i]) = 0 then begin
      Result := True;
      Break;
    end;
  end;
end;

function TPlayObject.IsGotoLabel(sMapName: string; nX, nY, nRange,
  nQuestFalgStatus: Integer;
  boQuestFalgStatus: Boolean; sItemName1, sItemName2: string; boNeedGroup:
  Boolean; nRandomCount: Integer): Boolean;
var
  n01                                   : Integer;
  nMaxCurrX, nMaxCurrY, nMinCurrX, nMinCurrY: Integer;

  function GetAllowItem: Boolean;
  begin
    Result := False;
    if sItemName1 = '*' then begin
      Result := True;
    end else
      if CompareText(sItemName1, sItemName2) = 0 then begin
        Result := True;
      end;
  end;

  function GetRandomCount: Boolean;
  begin
    Result := False;
    if nRandomCount = 0 then Result := True
    else
      if (nRandomCount > 0) and (Random(nRandomCount div 2 + nRandomCount) =
        nRandomCount) then Result := True;
  end;

  function GetGroup: Boolean;
  begin
    Result := False;
    if not boNeedGroup then Result := True
    else
      if m_GroupOwner <> nil then Result := True;
  end;
begin
  Result := False;
  nMaxCurrX := nX + nRange;
  nMaxCurrY := nY + nRange;
  nMinCurrX := nX - nRange;
  nMinCurrY := nY - nRange;
  if (CompareText(sMapName, m_sMapName) = 0) and (((m_nCurrX <= nMaxCurrX) and
    (m_nCurrX >= nMinCurrX) and (m_nCurrY <= nMaxCurrY) and (m_nCurrY >=
    nMinCurrY)) or (nRange = -1)) then begin
    if nQuestFalgStatus > 0 then begin
      n01 := GetQuestFalgStatus(nQuestFalgStatus);
      if (n01 = 0) and (not boQuestFalgStatus) then begin
        if GetAllowItem and GetGroup and GetRandomCount then begin
          Result := True;
        end;
      end else
        if (n01 <> 0) and (boQuestFalgStatus) then begin
          if GetAllowItem and GetGroup and GetRandomCount then begin
            Result := True;
          end;
        end;
    end else begin
      if GetAllowItem and GetGroup and GetRandomCount then begin
        Result := True;
      end;
    end;
  end;
end;

procedure TPlayObject.JoinGroup(PlayObject: TPlayObject);
begin
  m_GroupOwner := PlayObject;
  SendGroupText(Format(g_sJoinGroup, [m_sCharName]));
end;

function TPlayObject.LableIsCanJmp(sLabel: string; boLeft: Boolean): Boolean;
var
  i                                     : Integer;
begin
  Result := False;
  if CompareText(sLabel, '@main') = 0 then begin
    Result := True;
    Exit;
  end;
  if CompareText(sLabel, '@mainleft') = 0 then begin
    Result := True;
    Exit;
  end;
  if CompareText(sLabel, '@exit') = 0 then begin
    Result := True;
    Exit;
  end;
  if boLeft then begin
    for i := 0 to m_CanJmpScriptLableList2.Count - 1 do begin
      if CompareText(sLabel, m_CanJmpScriptLableList2.Strings[i]) = 0 then begin
        Result := True;
        Break;
      end;
    end;
  end;
  for i := 0 to m_CanJmpScriptLableList.Count - 1 do begin
    if CompareText(sLabel, m_CanJmpScriptLableList.Strings[i]) = 0 then begin
      Result := True;
      Break;
    end;
  end;
  if CompareText(sLabel, m_sPlayDiceLabel) = 0 then begin
    m_sPlayDiceLabel := '';
    Result := True;
    Exit;
  end;
end;

//登陆时间记费

procedure TPlayObject.LogonTimcCost();                                                              //004CA994
var
  n08                                   : Integer;
  SC                                    : string;
begin
  if (m_nPayMent = 2) or (g_Config.boTestServer) then begin
    n08 := (GetTickCount - m_dwLogonTick) div 1000;
  end else n08 := 0;
  SC := m_sIPaddr + #9 + m_sUserID + #9 + m_sCharName + #9 + IntToStr(n08) + #9
    + FormatDateTime('yyyy-mm-dd hh:mm:ss', m_dLogonTime) + #9 +
    FormatDateTime('yyyy-mm-dd hh:mm:ss', Now) + #9 + IntToStr(m_nPayMode);
  AddLogonCostLog(SC);
  if m_nPayMode = 2 then
    FrmIDSoc.SendLogonCostMsg(m_sUserID, n08 div 60);
end;

procedure TPlayObject.MakeFlagOwner(nflagType: Integer; ItemIdx: Integer; nX,
  nY: Integer; sData: string);
var
  tmpList                               : TList;
  NPC                                   : TNormNpc;
  wAppr                                 : word;
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  tmpList := TList.Create;
  try
    UserEngine.GetMerchantList(m_PEnvir, nX, nY, 0, tmpList);
    if tmpList.Count = 0 then begin
{$IF USESDK = DEBUG}
      SysMsg(Format('坐标(%d,%d)未发现有任何NPC', []), c_Red, t_Hint);
{$IFEND}
      Exit;
    end;
    NPC := TNormNpc(tmpList[0]);
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := pTUserItem(m_ItemList[i]);
      if UserItem.MakeIndex = ItemIdx then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem = nil then Break;
        wAppr := StdItem.AniCount;
        if NPC.SetFlagOwnerInfo(Self, wAppr, sData) then begin
          if UserItem.Dura <= 1 then begin
            SendDelItems(UserItem);
            Dispose(UserItem);
            m_ItemList.Delete(i);
          end else begin
            Dec(UserItem.Dura);
            SendUpdateItem(UserItem);
          end;
          SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
        end;
        Break;
      end;
    end;
  finally
    tmpList.free;
  end;
end;

procedure TPlayObject.MakeGhost;
var
  i, j                                  : Integer;
  sSayMsg                               : string;
  human                                 : TPlayObject;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::MakeGhost';
begin
  try
    if (g_HighLevelHuman = Self) then g_HighLevelHuman := nil;
    if (g_HighPKPointHuman = Self) then g_HighPKPointHuman := nil;
    if (g_HighDCHuman = Self) then g_HighDCHuman := nil;
    if (g_HighMCHuman = Self) then g_HighMCHuman := nil;
    if (g_HighSCHuman = Self) then g_HighSCHuman := nil;
    if (g_HighOnlineHuman = Self) then g_HighOnlineHuman := nil;
    //人物下线后通知配偶,并把对方的相关记录清空
    if m_DearHuman <> nil then begin
      if m_btGender = 0 then begin
        sSayMsg := AnsiReplaceText(g_sManLongOutDearOnlineMsg, '%d',
          m_sDearName);
        sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
        sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
        sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
        sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
        if g_Config.boOldClientShowHiLevel then
          m_DearHuman.SysMsg(sSayMsg, c_Red, t_Hint);
      end else begin
        sSayMsg := AnsiReplaceText(g_sWoManLongOutDearOnlineMsg, '%d',
          m_sDearName);
        sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
        sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
        sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
        sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
        if g_Config.boOldClientShowHiLevel then
          m_DearHuman.SysMsg(sSayMsg, c_Red, t_Hint);
      end;
      m_DearHuman.m_DearHuman := nil;
      m_DearHuman := nil;
    end;
    if (m_MasterHuman <> nil) or (m_MasterList.Count > 0) then begin
      if m_boMaster then begin
        for i := m_MasterList.Count - 1 downto 0 do begin
          human := TPlayObject(m_MasterList.Items[i]);
          sSayMsg := AnsiReplaceText(g_sMasterLongOutMasterListOnlineMsg, '%s',
            m_sCharName);
          sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
          sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
          sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
          if g_Config.boOldClientShowHiLevel then
            human.SysMsg(sSayMsg, c_Red, t_Hint);
          human.m_MasterHuman := nil;
        end;
      end else begin
        if m_MasterHuman = nil then Exit;
        sSayMsg := AnsiReplaceText(g_sMasterListLongOutMasterOnlineMsg, '%d',
          m_sMasterName[1]);
        sSayMsg := AnsiReplaceText(sSayMsg, '%s', m_sCharName);
        sSayMsg := AnsiReplaceText(sSayMsg, '%m', m_PEnvir.m_sMapDesc);
        sSayMsg := AnsiReplaceText(sSayMsg, '%x', IntToStr(m_nCurrX));
        sSayMsg := AnsiReplaceText(sSayMsg, '%y', IntToStr(m_nCurrY));
        if g_Config.boOldClientShowHiLevel then
          m_MasterHuman.SysMsg(sSayMsg, c_Red, t_Hint);

        //如果为大徒弟则将对方的记录清空
        if m_MasterHuman.m_sMasterName[1] = m_sCharName then begin
          m_MasterHuman.m_MasterHuman := nil;
        end;

        for i := 0 to m_MasterHuman.m_MasterList.Count - 1 do begin
          if m_MasterHuman.m_MasterList.Items[i] = Self then begin
            m_MasterHuman.m_MasterList.Delete(i);
            Break;
          end;
        end;
      end;
    end;

    //物品控制-下线掉落
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := pTUserItem(m_ItemList[i]);
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        if CheckSPCode(StdItem.Reserved, RE_OUTDROP) then begin
          if DropItemDown(UserItem, 5, True, nil, Self) then begin
            Dispose(pTUserItem(m_ItemList[i]));
            m_ItemList.Delete(i);
          end;
        end;
      end;
    end;
    SendMeOnlineState(0);

    if m_boPneuma and (m_PneumaObject <> nil) then begin                                            //元神的处理
      TPlayObject(m_PneumaObject).m_dwCallPneumaTick := GetTickCount;
      TPlayObject(m_PneumaObject).m_PneumaObject := nil;

      TPlayObject(m_PneumaObject).m_PetInfo[3].nMakeIndex := 0;
      TPlayObject(m_PneumaObject).m_PetInfo[3].wLevel := 0;
      TPlayObject(m_PneumaObject).m_PetInfo[3].btType := 0;
      TPlayObject(m_PneumaObject).m_PetInfo[3].btReLive := 0;
      TPlayObject(m_PneumaObject).m_PetInfo[3].btRideFightSpeed := 0;

   {   if m_boInosculatePneuma then begin
        if (m_MagicSkills[SKILL_SPIRITLINK] <> nil) then begin
          m_PneumaObject.SendDelayMsg(m_PneumaObject, RM_CHARSTATUSCHANGED_Delay, 0, 0, 0, 0, '', 500);
          m_PneumaObject.SysMsg('你和融合元神的灵魂锁链状态已解除', c_Red, t_Hint);
        end;
      end;    }

      m_PneumaObject := nil;
    end else if not m_boPneuma and (m_PneumaObject <> nil) then begin                               //主体的处理
      if not m_PneumaObject.m_boGhost and
        TPlayObject(m_PneumaObject).m_boOfflineGetGamePoint then
        UserEngine.KickPlayObject(m_PneumaObject.m_sCharName);
      m_dwCallPneumaTick := GetTickCount;
      TPlayObject(m_PneumaObject).m_PneumaObject := nil;
      m_PneumaObject := nil;
    end;

  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg);
      MainOutMessage(E.Message);
    end;
  end;
  inherited;
end;

procedure TPlayObject.MakeMine;                                                                     //004CB3AC

  function RandomDrua(): Integer;
  begin
    Result := Random(g_Config.nStoneGeneralDuraRate {13000}) +
      g_Config.nStoneMinDura {3000};
    if Random(g_Config.nStoneAddDuraRate {20}) = 0 then begin
      Result := Result + Random(g_Config.nStoneAddDuraMax {10000});
    end;
  end;
var
  UserItem                              : pTUserItem;
  nRANDOM                               : Integer;
begin
  if m_ItemList.Count >= m_nBagSize then Exit;

  nRANDOM := Random(g_Config.nStoneTypeRate {120});
  if nRANDOM in [g_Config.nGoldStoneMin {1}..g_Config.nGoldStoneMax {2}] then begin
    New(UserItem);
    if UserEngine.CopyToUserItemFromName(g_Config.sGoldStone, UserItem) then begin
      UserItem.Dura := RandomDrua();
      m_ItemList.Add(UserItem);
      WeightChanged();
      SendAddItem(UserItem);
    end else
      Dispose(UserItem);
    Exit;
  end;
  if nRANDOM in [g_Config.nSilverStoneMin {3}..g_Config.nSilverStoneMax {20}] then begin
    New(UserItem);
    if UserEngine.CopyToUserItemFromName(g_Config.sSilverStone, UserItem) then begin
      UserItem.Dura := RandomDrua();
      m_ItemList.Add(UserItem);
      WeightChanged();
      SendAddItem(UserItem);
    end else
      Dispose(UserItem);
    Exit;
  end;
  if nRANDOM in [g_Config.nSteelStoneMin {21}..g_Config.nSteelStoneMax {45}] then begin
    New(UserItem);
    if UserEngine.CopyToUserItemFromName(g_Config.sSteelStone, UserItem) then begin
      UserItem.Dura := RandomDrua();
      m_ItemList.Add(UserItem);
      WeightChanged();
      SendAddItem(UserItem);
    end else
      Dispose(UserItem);
    Exit;
  end;
  if nRANDOM in [g_Config.nBlackStoneMin {46}..g_Config.nBlackStoneMax {56}] then begin
    New(UserItem);
    if UserEngine.CopyToUserItemFromName(g_Config.sBlackStone, UserItem) then begin
      UserItem.Dura := RandomDrua();
      m_ItemList.Add(UserItem);
      WeightChanged();
      SendAddItem(UserItem);
    end else
      Dispose(UserItem);
    Exit;
  end;
  New(UserItem);
  if UserEngine.CopyToUserItemFromName(g_Config.sCopperStone, UserItem) then begin
    UserItem.Dura := RandomDrua();
    m_ItemList.Add(UserItem);
    WeightChanged();
    SendAddItem(UserItem);
  end else
    Dispose(UserItem);
end;

procedure TPlayObject.MobPlace(sX, sY, sMonName, sCount: string);                                   //004C1508
begin

end;

procedure TPlayObject.MoveToHome;
begin
  SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
  BaseObjectMove(m_sHomeMap, IntToStr(m_nHomeX), IntToStr(m_nHomeY));
end;

procedure TPlayObject.MoveToHomeRandom();
begin
  SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
  BaseObjectMove(m_sHomeMap, IntToStr(m_nHomeX - 9 + Random(19)), IntToStr(m_nHomeY - 9 + Random(19)));
end;
{打开交易对话框}

procedure TPlayObject.OpenDealDlg(BaseObject: TBaseObject);
begin
  m_boDealing := True;
  m_DealCreat := BaseObject;
  GetBackDealItems();
  SendDefMessage(SM_DEALMENU, 0, 0, 0, 0, m_DealCreat.m_sCharName);
  m_DealLastTick := GetTickCount();
end;

function TPlayObject.PetDoShopCanSellCount: Integer;
begin
  Result := 0;
  if m_PetInfo[1].nMakeIndex <> 0 then begin
    if m_PetInfo[1].btReLive > 0 then
      Result := 15
    else begin
      case m_PetInfo[1].wLevel of
        0, 1: Result := 0;
        2, 3: Result := 5;
        4, 5: Result := 10;
        6, 7: Result := 15;
      else
        Result := 0;
      end;
    end;
    Exit;
  end;
  if m_Pet = nil then Exit;
  if m_PetInfo[0].btReLive > 0 then
    Result := 15
  else begin
    case m_PetInfo[0].wLevel of
      0, 1: Result := 0;
      2, 3: Result := 5;
      4, 5: Result := 10;
      6, 7: Result := 15;
    else
      Result := 0;
    end;
  end;
end;

procedure TPlayObject.HorseHide;
var
  i                                     : Integer;
begin
  if (m_Horse <> nil) then begin
    for i := m_SlaveList.Count - 1 downto 0 do begin
      if m_SlaveList[i] = m_Horse then begin
        m_SlaveList.Delete(i);
        Break;
      end;
    end;
    SendDefMessage(34977, m_Horse.m_wAppr, 612, 0, 0, '');

    if (not m_Horse.m_boDeath) and (not m_Horse.m_boGhost) then
      m_Horse.MakeGhost;
  end;
  m_Horse := nil;
end;

procedure TPlayObject.PetHide(nMakeIndex: Integer);
var
  UserItem                              : pTUserItem;
  nCheckCount                           : Integer;
  i, nBagSize                           : Integer;
label
  return;
begin
  if (nMakeIndex = m_PetInfo[0].nMakeIndex) then begin
    if (m_Pet <> nil) then begin
      //删除宠物
      for i := m_SlaveList.Count - 1 downto 0 do begin
        if m_SlaveList[i] = m_Pet then begin
          m_SlaveList.Delete(i);
          Break;
        end;
      end;
      if (not m_Pet.m_boDeath) and (not m_Pet.m_boGhost) then
        m_Pet.MakeGhost;
      m_Pet := nil;
    end;
    m_PetInfo[0].nMakeIndex := 0;
    m_PetInfo[0].wLevel := 0;
    m_PetInfo[0].btType := 0;
    m_PetInfo[0].btReLive := 0;
    goto return;
  end;

  if (nMakeIndex = m_PetInfo[4].nMakeIndex) then begin
    m_PetInfo[4].nMakeIndex := 0;
    m_PetInfo[4].wLevel := 0;
    m_PetInfo[4].btType := 0;
    m_PetInfo[4].btReLive := 0;
    goto return;
  end;

  if (nMakeIndex = m_PetInfo[5].nMakeIndex) then begin
    for i := 0 to m_ItemList.Count - 1 do begin                                                     //包裹里的物品
      UserItem := m_ItemList.Items[i];
      if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
        UserItem.btItemExt[29] := 2;
        SendUpdateItem(UserItem, False);
        Break;
      end;
    end;
    m_boBeast := False;
    m_PetInfo[5].nMakeIndex := 0;
    m_PetInfo[5].wLevel := 0;
    m_PetInfo[5].btType := 0;
    m_PetInfo[5].btReLive := 0;
    SendRefMsg(RM_510, 1, 0, 171, 0, '');
    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  end;

  if m_boRideOn and (nMakeIndex = m_PetInfo[2].nMakeIndex) then begin
    m_dwLastRide := GetTickCount;
    m_boRideOn := False;
    m_boRideFightOn := False;
    SendRefMsg(RM_SITDOWN, m_btDirection, MakeLong(m_nCurrX, m_nCurrY), GetFeatureToLong(Self), 0, '');
    SendMsg(Self, RM_205, 0, 0, 0, 0, '');
    RecalcAbilitys();                                                                               //计算骑战属性
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
    m_PetInfo[2].nMakeIndex := 0;
    m_PetInfo[2].wLevel := 0;
    m_PetInfo[2].btType := 0;
    m_PetInfo[2].btReLive := 0;
    m_PetInfo[2].btRideFightSpeed := 0;
  end;

  if not m_boPneuma and (m_PneumaObject <> nil) and
    (TPlayObject(m_PneumaObject).m_boRideOn) and (nMakeIndex = m_PetInfo[3].nMakeIndex) then begin
    TPlayObject(m_PneumaObject).m_boRideOn := False;
    TPlayObject(m_PneumaObject).m_boRideFightOn := False;
    m_PneumaObject.SendRefMsg(RM_SITDOWN, m_PneumaObject.m_btDirection,
      MakeLong(m_PneumaObject.m_nCurrX, m_PneumaObject.m_nCurrY),
      m_PneumaObject.GetFeature(Self), 0, '');
    m_PneumaObject.SendMsg(m_PneumaObject, RM_205, 0, 0, 0, 0, '');
    m_PneumaObject.RecalcAbilitys();                                                                //计算骑战属性
    m_PneumaObject.SendMsg(m_PneumaObject, RM_ABILITY, 0, 0, 0, 0, '');
    m_PneumaObject.SendMsg(m_PneumaObject, RM_SUBABILITY, 0, 0, 0, 0, '');
    //通知所有人
    m_PneumaObject.SendRefMsg(RM_TURN,
      m_PneumaObject.m_btDirection,
      m_PneumaObject.m_nCurrX,
      m_PneumaObject.m_nCurrY,
      CalcCent(m_PneumaObject.m_WAbil.dwHP, m_PneumaObject.m_WAbil.dwMaxHP),
      m_PneumaObject.GetShowName);
    m_PetInfo[3].nMakeIndex := 0;
    m_PetInfo[3].wLevel := 0;
    m_PetInfo[3].btType := 0;
    m_PetInfo[3].btReLive := 0;
    m_PetInfo[3].btRideFightSpeed := 0;
  end;

  return:
  nBagSize := m_nPetBagSize;
  if (m_PetInfo[0].nMakeIndex = 0) and (m_PetInfo[1].nMakeIndex = 0) and
    (m_PetInfo[2].nMakeIndex = 0) and (m_PetInfo[3].nMakeIndex = 0) and
    (m_PetInfo[4].nMakeIndex = 0) and (m_PetInfo[5].nMakeIndex = 0) then
    nBagSize := 0;

  SendDefMessage(SM_PETBAGSIZE, Integer(Self), 0, m_nPetShopSize, nBagSize, '');
  if nBagSize = 0 then begin
    m_defMsg := MakeDefaultMsg(34977, 0, 100, 0, 0);
    SendSocket(@m_defMsg, EnCodeBuffer(@nMakeIndex, 4));
  end;
end;

//丛林豹捡东西

function TPlayObject.PetPickUpItem(nX, nY: Integer): Boolean;
begin
  Result := False;
  if m_Pet = nil then Exit;
  m_Pet.m_nTargetX := nX;
  m_Pet.m_nTargetY := nY;
  m_nPetTargetX := nX;
  m_nPetTargetY := nY;
  Result := True;
end;

procedure TPlayObject.PetShow(nMakeIndex: Integer);
resourcestring
  sHint1                                = '此处不能放出海底灵兽';
const
  PETBAGSIZE                            : array[0..7] of Integer = (0, 5, 5, 10, 10, 10, 10, 10);
  PETMAXHP                              : array[0..7] of Integer = (800, 1000, 1200, 1450, 1800, 2200, 2600, 3200);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nLevel, nType, nAppr                  : Integer;
  boFound                               : Boolean;
begin
  m_dwLastRide := GetTickCount;
  boFound := False;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList[i];
    if UserItem.MakeIndex = nMakeIndex then begin
      boFound := True;
      Break;
    end;
  end;

  if not boFound then Exit;

  StdItem := UserEngine.GetStdItem(UserItem.wIndex);
  if (StdItem <> nil) and (StdItem.StdMode = 49) and (StdItem.Shape = 51) then begin
    m_sPetName := UserItem.sExName;
    m_PetInfo[0].sCharName := m_sPetName;
    m_PetInfo[0].nMakeIndex := UserItem.MakeIndex;
    m_PetInfo[0].wLevel := MakeWord(UserItem.btValue[4], UserItem.btValue[5]);                      //等级
    m_PetInfo[0].btReLive := UserItem.btValue[9];                                                   //转生次数

    m_PetInfo[0].btRideFightSpeed := UserItem.btRideSpeed;                                          //骑战速度
    m_PetInfo[0].boUnWater := (UserItem.btItemExt[24] <> 0);                                        //避水灵性
    m_PetInfo[0].btSoul := byte(UserItem.btItemExt[29] >= 2);                                       //魂佑灵兽
    m_PetInfo[0].btAttack := UserItem.btExtra.btAttack;                                             //骑战技能攻击距离
    nAppr := UserItem.btValue[8];                                                                   //外观类型
    nType := StdItem.AniCount;                                                                      //灵兽类型
  end;

  if (nType = 5) and (not m_PEnvir.m_MapFlag.boCanRideShark) then begin
    SysMsg(sHint1, c_Red, t_Hint);
    m_PetInfo[0].nMakeIndex := 0;
    Exit;
  end;

  nLevel := _MIN(7, m_PetInfo[0].wLevel);

  if m_Pet = nil then begin
    if nAppr > 0 then
      m_Pet := TAnimalObject(MakeSlave(_PETNAME[_MIN(15, nType)][_MIN(3, m_PetInfo[0].btReLive)] + IntToStr(nAppr), m_PetInfo[0].wLevel, m_PetInfo[0].wLevel, 100, 86400, -1))
    else
      m_Pet := TAnimalObject(MakeSlave(_PETNAME[_MIN(15, nType)][_MIN(3, m_PetInfo[0].btReLive)], m_PetInfo[0].wLevel, m_PetInfo[0].wLevel, 100, 86400, -1));
  end;

  if m_Pet <> nil then begin
    m_Pet.m_boIsPet := True;

    m_Pet.m_boNoAttackMode := True;

    if m_PetInfo[0].btReLive > 0 then
      m_nPetBagSize := _Max(10, m_nPetBagSize)
    else
      m_nPetBagSize := _Max(PETBAGSIZE[nLevel], m_nPetBagSize);

    m_Pet.m_WAbil.dwHP := PETMAXHP[nLevel];
    m_Pet.m_WAbil.dwMaxHP := PETMAXHP[nLevel];

    if (m_PetInfo[0].btReLive = 2) and (UserItem.btItemExt[29] >= 2) then                           //魂佑灵兽
      m_Pet.m_btGender := $0A
    else
      m_Pet.m_btGender := m_PetInfo[0].btReLive;

    m_Pet.m_wExtraLevel := UserItem.btItemExt[30];                                                  //强化次数

    SendMsg(Self, RM_PETBAGITEMS, 0, 0, 0, 0, '');
    //如果是踏云豹
    if m_PetInfo[0].btReLive > 0 then begin
      case nType of
        0: m_PetInfo[0].btType := 11 + nAppr;
        1: m_PetInfo[0].btType := 13 + nAppr;
        2: m_PetInfo[0].btType := 16 + nAppr;
        3: m_PetInfo[0].btType := 19 + nAppr;
        4: m_PetInfo[0].btType := 22 + nAppr;
        5: m_PetInfo[0].btType := 25 + nAppr;
        6: m_PetInfo[0].btType := 28 + nAppr;
        7: m_PetInfo[0].btType := 31 + nAppr;
        8: m_PetInfo[0].btType := 34 + nAppr;
        9: m_PetInfo[0].btType := 37 + nAppr;
        10: m_PetInfo[0].btType := 38 + nAppr;
        11: m_PetInfo[0].btType := 43 + nAppr;
        12: m_PetInfo[0].btType := 44 + nAppr;
        13: m_PetInfo[0].btType := 45 + nAppr;
        14: m_PetInfo[0].btType := 40 + nAppr;
        15: m_PetInfo[0].btType := 46 + nAppr;
      end;
    end else begin
      case nType of
        0: m_PetInfo[0].btType := 11;
        1: m_PetInfo[0].btType := 14;
        2: m_PetInfo[0].btType := 17;
        3: m_PetInfo[0].btType := 20;
        4: m_PetInfo[0].btType := 23;
        5: m_PetInfo[0].btType := 26;
        6: m_PetInfo[0].btType := 29;
        7: m_PetInfo[0].btType := 32;
        8: m_PetInfo[0].btType := 35;
        9: m_PetInfo[0].btType := 38;
        10: m_PetInfo[0].btType := 39;
        11: m_PetInfo[0].btType := 44;
        12: m_PetInfo[0].btType := 45;
        13: m_PetInfo[0].btType := 46;
        14: m_PetInfo[0].btType := 41;
        15: m_PetInfo[0].btType := 47;
      end;
    end;
    //丛林豹出现
    //m_Pet.TurnTo(m_btDirection);
    SendPetInfo($01);
  end;

  m_nPetTargetX := -1;
  m_nPetTargetY := -1;
end;

function TPlayObject.PetStoreAddExp(nPetItemIdx, nExp, nDay: Integer; boEat: Boolean): Boolean;
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  w, wLevel, wMaxLevel                  : word;
  tm, Upexp, dwExp                      : DWORD;
begin
  Result := False;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if (m_Pet <> nil) and (UserItem <> nil) and (UserItem.MakeIndex = nPetItemIdx) then begin
      wLevel := UserItem.wLevel;                                                                    //等级
      dwExp := UserItem.dwExp;                                                                      //经验
      Inc(dwExp, nExp);
      Upexp := GetPetUpExp(UserItem.btValue[9], wLevel);
      wMaxLevel := g_Config.nPetMaxLevel[_MIN(3, UserItem.btValue[9])];
      if (Upexp > 0) and (dwExp > Upexp) and (wMaxLevel > wLevel) then begin
        while (dwExp > Upexp) do begin
          Inc(wLevel);
          Dec(dwExp, Upexp);
          Upexp := GetPetUpExp(UserItem.btValue[9], wLevel);
          if wLevel >= wMaxLevel then Break;
        end;
        ExecuteScript(g_FunctionNPC, '@PetUpLevel');
      end;
      if m_Pet <> nil then begin
        m_Pet.m_wSlaveExpLevel := _MIN(High(word), wLevel);
        m_Pet.RefShowName;
        m_PetInfo[0].wLevel := wLevel;
      end;
      UserItem.wLevel := wLevel;
      UserItem.dwExp := dwExp;

      if UserItem.btValue[9] < 3 then
        SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 3, nPetItemIdx, 0, '', 200)                     //刷新灵兽排名
      else
        SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 4, nPetItemIdx, 0, '', 200);

      nDay := _Max(1, nDay);
      tm := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
      tm := tm + nDay * 86400;
      //喂养时间
      //tm := DateTimeToWolTIme(Now);                                                                 //AddDateTimeOfDay(Now, 2)
      UserItem.btValue[0] := LoByte(LoWord(tm));
      UserItem.btValue[1] := HiByte(LoWord(tm));
      UserItem.btValue[2] := LoByte(HiWord(tm));
      UserItem.btValue[3] := HiByte(HiWord(tm));

      if boEat then
        SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
      SendUpdateItem(UserItem);
      Result := True;
      Break;
    end;
  end;
end;

function TPlayObject.PileStones(nX, nY: Integer): Boolean;                                          //004CB64C
var
  Event                                 : TEvent;
  PileEvent                             : TEvent;
  s1C                                   : string;
begin
  Result := False;
  if not m_PEnvir.m_MapFlag.boMINE then Exit;

  s1C := '';
  Event := TEvent(m_PEnvir.GetEvent(nX, nY));
  if (Event <> nil) and (Event.m_nEventType = ET_STONEMINE) then begin
    if TStoneMineEvent(Event).m_nMineCount > 0 then begin
      Dec(TStoneMineEvent(Event).m_nMineCount);
      if (Random(g_Config.nMakeMineHitRate {4}) = 0) then begin
        PileEvent := TEvent(m_PEnvir.GetEvent(m_nCurrX, m_nCurrY));
        if PileEvent = nil then begin
          PileEvent := TPileStones.Create(m_PEnvir, m_nCurrX, m_nCurrY, ET_PILESTONES, 5 * 60 * 1000);
          g_EventManager.AddEvent(PileEvent);
        end else begin
          if PileEvent.m_nEventType = ET_PILESTONES then
            TPileStones(PileEvent).AddEventParam;
        end;
        if Random(g_Config.nMakeMineRate {12}) = 0 then begin
          if (m_PEnvir.m_MapFlag.sMINELabel = '') then begin
            MakeMine();
          end else ExecuteScript(g_FunctionNPC, m_PEnvir.m_MapFlag.sMINELabel);
        end;
        s1C := '1';
        DoDamageWeapon(Random(15) + 5);
        Result := True;
      end;
    end else begin
      if (GetTickCount - TStoneMineEvent(Event).m_dwAddStoneMineTick) > 10 * 60 * 1000 then
        TStoneMineEvent(Event).AddStoneMine();
    end;
  end;
  SendRefMsg(RM_HEAVYHIT, m_btDirection, m_nCurrX, m_nCurrY, 0, s1C);
end;

procedure TPlayObject.PKDie(PlayObject: TPlayObject);
var
  nWinLevel, nLostLevel, nWinExp, nLostExp: Integer;
  boWinLEvel, boLostLevel, boWinExp, boLostExp: Boolean;
begin
  nWinLevel := g_Config.nKillHumanWinLevel;
  nLostLevel := g_Config.nKilledLostLevel;
  nWinExp := g_Config.nKillHumanWinExp;
  nLostExp := g_Config.nKillHumanLostExp;

  boWinLEvel := g_Config.boKillHumanWinLevel;
  boLostLevel := g_Config.boKilledLostLevel;
  boWinExp := g_Config.boKillHumanWinExp;
  boLostExp := g_Config.boKilledLostExp;

  if m_PEnvir.m_MapFlag.boPKWINLEVEL then begin
    boWinLEvel := True;
    nWinLevel := m_PEnvir.m_MapFlag.nPKWINLEVEL;
  end;
  if m_PEnvir.m_MapFlag.boPKLOSTLEVEL then begin
    boLostLevel := True;
    nLostLevel := m_PEnvir.m_MapFlag.nPKLOSTLEVEL;
  end;
  if m_PEnvir.m_MapFlag.boPKWINEXP then begin
    boWinExp := True;
    nWinExp := m_PEnvir.m_MapFlag.nPKWINEXP;
  end;
  if m_PEnvir.m_MapFlag.boPKLOSTEXP then begin
    boLostExp := True;
    nLostExp := m_PEnvir.m_MapFlag.nPKLOSTEXP;
  end;

  //宗族徽记
  if (PlayObject.m_MyClan <> nil) and (PlayObject.m_MyGuild <> nil) then begin
    if (TClan(PlayObject.m_MyClan).ClanInsignia <> '') then begin
      m_ClanInsignia.sClanName := TClan(PlayObject.m_MyClan).ChiefName;
      m_ClanInsignia.sGuildName := TGuild(PlayObject.m_MyGuild).sGuildName;
      m_ClanInsignia.sInsignia := TClan(PlayObject.m_MyClan).ClanInsignia;
      m_ClanInsignia.Time := DateTimeToWolTimeEx(Now());
      g_PacketManage3.Init;
      g_PacketManage3.WriteInteger(1);
      g_PacketManage3.WriteInteger(Integer(Self));
      g_PacketManage3.WriteString(m_ClanInsignia.sClanName, SizeOf(m_ClanInsignia.sClanName));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteString(m_ClanInsignia.sGuildName, SizeOf(m_ClanInsignia.sGuildName));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteString(m_ClanInsignia.sInsignia, SizeOf(m_ClanInsignia.sInsignia));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteInteger(m_ClanInsignia.Time);
      SendDefMessage(2119, Integer(Self), 0, 0, 0, g_PacketManage3.GetMsg(), True);
      SysMsg(Format('你被%s宗族成员击杀,已印上该宗族徽记', [m_ClanInsignia.sClanName]), c_Red, t_Hint);
    end;
  end;

  if PlayObject.m_Abil.level - m_Abil.level > g_Config.nHumanLevelDiffer then begin
    if not PlayObject.IsGoodKilling(Self) then begin
      PlayObject.IncPkPoint(g_Config.nKillHumanAddPKPoint {100});
      PlayObject.SysMsg(g_sYouMurderedMsg {'你犯了谋杀罪!!!'},
        c_Red, t_Hint);
      SysMsg(Format(g_sYouKilledByMsg, [m_LastHiter.m_sCharName]), c_Red,
        t_Hint);
      PlayObject.AddBodyLuck(-g_Config.nKillHumanDecLuckPoint {500});
      if PKLevel < 1 then
        if Random(5) = 0 then
          PlayObject.MakeWeaponUnlock;
      if g_FunctionNPC <> nil then begin
        //谋杀他人执行脚本
        PlayObject.m_sScriptParam[0] := m_sCharName;
        PlayObject.m_sScriptParam[1] := m_PEnvir.m_sMapName;
        PlayObject.m_sScriptParam[2] := IntToStr(m_nCurrX);
        PlayObject.m_sScriptParam[3] := IntToStr(m_nCurrY);
        PlayObject.m_sScriptParam[4] := m_PEnvir.m_sMapDesc;
        PlayObject.m_sScriptParam[5] := IntToStr(m_btCountry);
        PlayObject.ExecuteScript(g_FunctionNPC, '@谋杀他人');
        //被人谋杀执行脚本
        m_sScriptParam[0] := PlayObject.m_sCharName;
        m_sScriptParam[1] := PlayObject.m_PEnvir.m_sMapName;
        m_sScriptParam[2] := IntToStr(PlayObject.m_nCurrX);
        m_sScriptParam[3] := IntToStr(PlayObject.m_nCurrY);
        m_sScriptParam[4] := PlayObject.m_PEnvir.m_sMapDesc;
        m_sScriptParam[5] := IntToStr(PlayObject.m_btCountry);
        ExecuteScript(g_FunctionNPC, '@被人谋杀');
      end;
    end else begin
      PlayObject.SysMsg(g_sYouProtectedByLawOfDefense {'[你受到正当规则保护。]'}, c_Green, t_Hint);
      if g_FunctionNPC <> nil then begin
        //杀红名人物执行脚本
        PlayObject.m_sScriptParam[0] := m_sCharName;
        PlayObject.m_sScriptParam[1] := m_PEnvir.m_sMapName;
        PlayObject.m_sScriptParam[2] := IntToStr(m_nCurrX);
        PlayObject.m_sScriptParam[3] := IntToStr(m_nCurrY);
        PlayObject.m_sScriptParam[4] := m_PEnvir.m_sMapDesc;
        PlayObject.m_sScriptParam[5] := IntToStr(m_btCountry);
        PlayObject.ExecuteScript(g_FunctionNPC, '@杀死红名');
        //红名被杀执行脚本
        m_sScriptParam[0] := PlayObject.m_sCharName;
        m_sScriptParam[1] := PlayObject.m_PEnvir.m_sMapName;
        m_sScriptParam[2] := IntToStr(PlayObject.m_nCurrX);
        m_sScriptParam[3] := IntToStr(PlayObject.m_nCurrY);
        m_sScriptParam[4] := PlayObject.m_PEnvir.m_sMapDesc;
        m_sScriptParam[5] := IntToStr(PlayObject.m_btCountry);
        ExecuteScript(g_FunctionNPC, '@红名被杀');
      end;
    end;
    Exit;
  end;
  if boWinLEvel then begin
    if PlayObject.m_Abil.level + nWinLevel <= _MIN(MAXUPLEVEL, g_Config.nLimitLevel) then begin
      Inc(PlayObject.m_Abil.level, nWinLevel);
    end else begin
      PlayObject.m_Abil.level := _MIN(MAXUPLEVEL, g_Config.nLimitLevel);
    end;
    PlayObject.HasLevelUp(PlayObject.m_Abil.level - nWinLevel);

    if boLostLevel then begin
      if PKLevel >= 2 then begin
        if m_Abil.level >= nLostLevel * 2 then
          Dec(m_Abil.level, nLostLevel * 2);
      end else begin
        if m_Abil.level >= nLostLevel then
          Dec(m_Abil.level, nLostLevel);
      end;
    end;
  end;

  if boWinExp then begin
    PlayObject.WinExp(nWinExp, 0, 0);
    if boLostExp then begin
      if m_Abil.Exp >= LongWord(nLostExp) then begin
        if m_Abil.Exp >= LongWord(nLostExp) then begin
          Dec(m_Abil.Exp, LongWord(nLostExp));
        end else begin
          m_Abil.Exp := 0;
        end;
      end else begin
        if m_Abil.level >= 1 then begin
          Dec(m_Abil.level);
          Inc(m_Abil.Exp, GetLevelExp(m_Abil.level));
          if m_Abil.Exp >= LongWord(nLostExp) then begin
            Dec(m_Abil.Exp, LongWord(nLostExp));
          end else begin
            m_Abil.Exp := 0;
          end;
        end else begin
          m_Abil.level := 0;
          m_Abil.Exp := 0;
        end;
        //HasLevelUp(m_Abil.Level + 1);
      end;
    end;
  end;
end;

procedure TPlayObject.PneumaLogin;
resourcestring
  sHint1                                = '请等待5秒后再释放或收起你的元神分身。';
  sHint2                                = '神奇的力量散去,你的元神分身开始沉睡。';
  sHint3                                = '元神分身不能再有分身';
  sHint4                                = '你还没有修炼元神,或者你的元神还没有化体';
  sHint5                                = '你不能连续唤醒元神分身,这样会给分身造成伤害。';
  sHint6                                = '元神分身的魂魄力量还很虚弱,过一段时间才能重新凝聚。';
  sHint7                                = '本地图禁止释放元神。';
begin
  if not m_boLoginNoticeOK then Exit;

  if m_PneumaObject <> nil then begin                                                               //收起元神
    TPlayObject(m_PneumaObject).m_boSoftClose := True;
    TPlayObject(m_PneumaObject).m_boReconnection := True;
    TPlayObject(m_PneumaObject).SendRefMsg(RM_510, 1, 0, 42, 0, '');
    TPlayObject(m_PneumaObject).SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
    m_PneumaObject := nil;
    m_dwCallPneumaTick := GetTickCount;
    SysMsg(sHint2, c_Red, t_Hint);

    m_PetInfo[3].nMakeIndex := 0;
    m_PetInfo[3].wLevel := 0;
    m_PetInfo[3].btType := 0;
    m_PetInfo[3].btReLive := 0;
    m_PetInfo[3].btRideFightSpeed := 0;
  end else begin
    if (GetTickCount - m_dwCallPneumaTick < 3000) then begin
      SysMsg(sHint1, c_Red, t_Hint);
      Exit;
    end;
    //检查是否有元神
    if m_boPneuma then begin
      SysMsg(sHint3, c_Red, t_Hint);
      Exit;
    end;
    if m_btPneumaSex = 0 then begin
      SysMsg(sHint4, c_Red, t_Hint);
      Exit;
    end;
    //检查上次释放时间间隔
    if GetTickCount - m_dwCallPneumaTick < 3000 then begin
      SysMsg(sHint5, c_Red, t_Hint);
      Exit;
    end;
    if GetTickCount - m_dwCallPneumaTick < 5000 then begin
      SysMsg(sHint6, c_Red, t_Hint);
      Exit;
    end;
    if m_PEnvir.m_MapFlag.boNoPneuma then begin
      SysMsg(sHint7, c_Red, t_Hint);
      Exit;
    end;
    SendDefMessage(SM_9607, 0, 0, 0, 0, m_sPneumaName);
    m_dwCallPneumaTick := GetTickCount;
  end;
end;

procedure TPlayObject.ProcessClientPassword(ProcessMsg: pTProcessMessage);
var
  nLen                                  : Integer;
  sData                                 : string;
begin
  //  SysMsg(ProcessMsg.sMsg,c_Red,t_Hint);
  if ProcessMsg.wParam = 0 then begin
    ProcessUserLineMsg('@' + g_GameCommand.UnLock.sCmd, 0);
    Exit;
  end;

  sData := ProcessMsg.sMsg;
  nLen := Length(sData);
  if m_boSetStoragePwd then begin
    m_boSetStoragePwd := False;
    if (nLen > 3) and (nLen < 8) then begin
      m_sTempPwd := sData;
      m_boReConfigPwd := True;
      SysMsg(g_sReSetPasswordMsg, c_Green, t_Hint);
      {'请重复输入一次仓库密码:'}
      SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
    end else begin
      SysMsg(g_sPasswordOverLongMsg, c_Red, t_Hint);
      {'输入的密码长度不正确!!!,密码长度必须在 4 - 7 的范围内,请重新设置密码。'}
    end;
    Exit;
  end;
  if m_boReConfigPwd then begin
    m_boReConfigPwd := False;
    if CompareStr(m_sTempPwd, sData) = 0 then begin
      m_sStoragePwd := sData;
      m_boPasswordLocked := True;
      m_sTempPwd := '';
      SysMsg(g_sReSetPasswordOKMsg, c_Blue, t_Hint);
      {'密码设置成功!!,仓库已经自动上锁,请记好您的仓库密码,在取仓库时需要使用此密码开锁。'}
    end else begin
      m_sTempPwd := '';
      SysMsg(g_sReSetPasswordNotMatchMsg, c_Red, t_Hint);
    end;
    Exit;
  end;
  if m_boUnLockPwd or m_boUnLockStoragePwd then begin
    if CompareStr(m_sStoragePwd, sData) = 0 then begin
      m_boPasswordLocked := False;
      if m_boUnLockPwd then begin
        if g_Config.boLockDealAction then m_boCanDeal := True;
        if g_Config.boLockDropAction then m_boCanDrop := True;
        if g_Config.boLockWalkAction then m_boCanWalk := True;
        if g_Config.boLockRunAction then m_boCanRun := True;
        if g_Config.boLockHitAction then m_boCanHit := True;
        if g_Config.boLockSpellAction then m_boCanSpell := True;
        if g_Config.boLockSendMsgAction then m_boCanSendMsg := True;
        if g_Config.boLockUserItemAction then m_boCanUseItem := True;
        if g_Config.boLockInObModeAction then begin
          m_boObMode := False;
          m_boAdminMode := False;
        end;
        m_boLockLogoned := True;
        SysMsg(g_sPasswordUnLockOKMsg, c_Blue, t_Hint);
      end;
      if m_boUnLockStoragePwd then begin
        if g_Config.boLockGetBackItemAction then m_boCanGetBackItem := True;
        SysMsg(g_sStorageUnLockOKMsg, c_Blue, t_Hint);
      end;
    end else begin
      Inc(m_btPwdFailCount);
      SysMsg(g_sUnLockPasswordFailMsg, c_Red, t_Hint);
      if m_btPwdFailCount > 3 then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
      end;
    end;
    m_boUnLockPwd := False;
    m_boUnLockStoragePwd := False;
    Exit;
  end;

  if m_boCheckOldPwd then begin
    m_boCheckOldPwd := False;
    if m_sStoragePwd = sData then begin
      SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
      SysMsg(g_sSetPasswordMsg, c_Green, t_Hint);
      m_boSetStoragePwd := True;
    end else begin
      Inc(m_btPwdFailCount);
      SysMsg(g_sOldPasswordIncorrectMsg, c_Red, t_Hint);
      if m_btPwdFailCount > 3 then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        m_boPasswordLocked := True;
      end;
    end;
    Exit;
  end;
end;

//处理发言消息(CM_SAY消息)

procedure TPlayObject.ProcessSayMsg(sData: string; nMsgType: Integer);
var
  boDisableSayMsg                       : Boolean;
  SC, sCryCryMsg, sParam1               : string;
  Hum                                   : TPlayObject;
  Country                               : TCountry;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject.ProcessSayMsg Msg = %s';
  sEnvirNilMsg                          = '[Exception] ProcessSayMsg nil PEnvir Name = %s Msg = %s MsgType = %d';
  sHint1                                = '本行会禁止聊天!';
  sHint2                                = '本地图禁止聊天!';
begin
  if Length(sData) = 0 then Exit;

  if m_PEnvir = nil then begin
    MainOutMessage(Format(sEnvirNilMsg, [m_sCharName, sData, nMsgType]));
    Exit;
  end;

  try
    if m_PEnvir.m_MapFlag.boNOSAY or (m_PEnvir.m_MapFlag.boSECRET and ((m_PEnvir.m_MapFlag.btSECRETRule and SECRET_RULE_DISABLESAY) <> 0)) then begin
      SysMsg(sHint2 {'本地图禁止聊天!'}, c_Red, t_Hint);
      Exit;
    end;

    if Length(sData) > g_Config.nSayMsgMaxLen then begin
      if sData[1] <> '#' then
        sData := Copy(sData, 1, g_Config.nSayMsgMaxLen);
    end;

    if ((GetTickCount - m_dwSayMsgTick) < g_Config.dwSayMsgTime {3 * 1000}) then begin
      Inc(m_nSayMsgCount);
      if m_nSayMsgCount >= g_Config.nSayMsgCount {2} then begin
        m_boDisableSayMsg := True;
        m_dwDisableSayMsgTick := GetTickCount + g_Config.dwDisableSayMsgTime {60 * 1000};
        SysMsg(Format(g_sDisableSayMsg, [g_Config.dwDisableSayMsgTime div (60 * 1000)]), c_Red, t_Hint); //'[由于你重复发相同的内容,%d分钟内你将被禁止发言...]'
      end;
    end else begin                                                                                  //004D4DF6
      m_dwSayMsgTick := GetTickCount();
      m_nSayMsgCount := 0;
    end;

    if GetTickCount >= m_dwDisableSayMsgTick then m_boDisableSayMsg := False;
    boDisableSayMsg := m_boDisableSayMsg;
    g_DenySayMsgList.Lock;
    try
      if g_DenySayMsgList.GetIndex(m_sCharName) >= 0 then
        boDisableSayMsg := True;
    finally
      g_DenySayMsgList.UnLock;
    end;
    if not boDisableSayMsg then begin
      m_sOldSayMsg := sData;
      //如果是交易消息
      if nMsgType = 3 then begin
        SC := GetValidStr3(sData, sParam1, [' ']);
        if not m_boFilterSendMsg then
          Whisper(sParam1, SC, 2);
        Exit;
      end;
      if sData[1] = '/' then begin
        SC := Copy(sData, 2, Length(sData) - 1);
        //查询在线人数
        if CompareText(Trim(SC), Trim(g_GameCommand.WHO.sCmd)) = 0 then begin
          if (m_btPermissionGM < g_GameCommand.WHO.nPermissionMin) then begin
            SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
            Exit;
          end;
          HearMsg(Format(g_sOnlineCountMsg, [UserEngine.OnlinePlayerCount]) + ',其中脱机人数:' + IntToStr(UserEngine.OffLinePlayerCount));
          Exit;
        end;
        if CompareText(Trim(SC), Trim(g_GameCommand.TOTAL.sCmd)) = 0 then begin
          if (m_btPermissionGM < g_GameCommand.TOTAL.nPermissionMin) then begin
            SysMsg(g_sGameCommandPermissionTooLow, c_Red, t_Hint);
            Exit;
          end;
          HearMsg(Format(g_sTotalOnlineCountMsg, [g_nTotalHumCount]));
          Exit;
        end;
        SC := GetValidStr3(SC, sParam1, [' ']);
        if not m_boFilterSendMsg then Whisper(sParam1, SC);
        Exit;
      end;
      if sData[1] = '!' then begin
        if Length(sData) >= 2 then begin
          if sData[2] = '!' then begin
            SC := Copy(sData, 3, Length(sData) - 2);
            SendGroupText(m_sCharName + ': ' + SC);
            Exit;
          end;
          if sData[2] = '~' then begin
            if m_MyGuild <> nil then begin
              if TGuild(m_MyGuild).m_boBanGuildChat then begin
                SC := Copy(sData, 3, Length(sData) - 2);
                TGuild(m_MyGuild).SendGuildMsg(m_sCharName + ': ' + SC);
                UserEngine.SendServerGroupMsg(SS_208, g_Config.nServerNumber, TGuild(m_MyGuild).sGuildName + '/' + m_sCharName + '/' + SC);
              end else begin
                SysMsg(sHint1, c_Red, t_Hint);
              end;
            end;
            Exit;
          end;
          //国家聊天模式
{$IF COUNTRYSYSTEM = 1}
          if sData[2] = '@' then begin
            Country := GetCountryInfo(m_btCountry);
            if Country.btCode <> 0 then begin
              SC := Copy(sData, 3, Length(sData) - 2);
              UserEngine.SendBroadCastMsg(m_sCharName + '[' + Country.sName + ']:' + SC, t_Country, 0, 0, m_btCountry);
            end else begin
              SysMsg('你没有加入任何国家...', c_Pink, t_Hint);
            end;
            Exit;
          end;
{$IFEND}
        end;                                                                                        //004D512C
        if not m_PEnvir.m_MapFlag.boQUIZ then begin
          if (GetTickCount - m_dwShoutMsgTick) > 10 * 1000 then begin
            if m_Abil.level <= g_Config.nCanShoutMsgLevel then begin
              SysMsg(Format(g_sYouNeedLevelMsg, [g_Config.nCanShoutMsgLevel + 1]), c_Red, t_Hint);
              Exit;
            end;
            m_dwShoutMsgTick := GetTickCount();
            SC := Copy(sData, 2, Length(sData) - 1);
            sCryCryMsg := '(!)' + m_sCharName + ': ' + SC;
            if m_boFilterSendMsg then begin
              SendMsg(nil, RM_CRY, 0, 0, $FFFF, 0, sCryCryMsg);
            end else begin
              UserEngine.CryCry(RM_CRY, m_PEnvir, m_nCurrX, m_nCurrY, 50,
                g_Config.btCryMsgFColor, g_Config.btCryMsgBColor, sCryCryMsg);
            end;
            Exit;
          end;
          SysMsg(Format(g_sYouCanSendCyCyLaterMsg, [10 - (GetTickCount - m_dwShoutMsgTick) div 1000]), c_Red, t_Hint);
          Exit;
        end;
        SysMsg(g_sThisMapDisableSendCyCyMsg, c_Red, t_Hint);
        Exit;
      end;
      if sData[1] = '#' then begin                                                                  //2016.12.26有可疑
        if Length(sData) >= 2 then begin
          if sData[2] = '#' then begin
            SC := Copy(sData, 3, Length(sData) - 2);
            SC := GetValidStr3(SC, sParam1, [' ']);
            Hum := UserEngine.GetPlayObject(sParam1);
            if Hum <> nil then begin
              Hum.SendDefMessage(38, 0, 0, 0, 0, m_sCharName + '/' + FormatDateTime('yyyymmdd', Now) + '/' + FormatDateTime('hh:nn:ss', Now) + '/' + SC);
            end;
            Exit;
          end;
        end;
      end;
      //宗族消息
      if sData[1] = '$' then begin
        if m_MyClan <> nil then begin
          SC := Copy(sData, 2, Length(sData) - 1);
          TClan(m_MyClan).SendClanMsg(m_sCharName + ': ' + SC);
        end;
        Exit;
      end;
      if m_boFilterSendMsg then begin                                                               //如果禁止发信息,则只向自己发信息
        SendMsg(Self, RM_HEAR, 0, g_Config.btHearMsgFColor,
          g_Config.btHearMsgBColor, MakeWord(m_btChatColor, m_btChatFont), m_sCharName + ':' + sData);
      end else begin
        inherited;
      end;
      Exit;
    end;
    SysMsg(g_sYouIsDisableSendMsg {'禁止聊天'}, c_Red, t_Hint);
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [sData]));
      MainOutMessage(E.Message);
    end;
  end;
end;

//祈祷套装

procedure TPlayObject.ProcessSpiritSuite();
var
  i                                     : Integer;
  StdItem                               : pTStdItem;
  UseItem                               : pTUserItem;
resourcestring
  sHint1                                = '@TakeOff';
  sHint2                                = '神之祈祷,天地震怒,尸横遍野...';
  sHint3                                = '祈祷发出强烈的宇宙效应';
begin
  if not g_Config.boSpiritMutiny or not m_bopirit then Exit;
  m_bopirit := False;
  for i := Low(THumItems) to High(THumItems) do begin
    UseItem := @m_UseItems[i];
    if UseItem.wIndex <= 0 then Continue;
    StdItem := UserEngine.GetStdItem(UseItem.wIndex);
    if (StdItem <> nil) and (StdItem.Shape in [126..129]) then begin
      SendDelItems(UseItem);
      m_sScriptParam[0] := StdItem.Name;
      m_sScriptParam[1] := StdItem.FilterName;
      UseItem.wIndex := 0;
    end;
  end;
  RecalcAbilitys(True);
  g_dwSpiritMutinyTick := GetTickCount + g_Config.dwSpiritMutinyTime;
  UserEngine.SendBroadCastMsgExt(sHint2, t_System);
  SysMsg(sHint3, c_Green, t_Hint);
end;

function TPlayObject.ProcessUserCmd(sCmd, sParam1, sParam2, sParam3, sParam4,
  sParam5, sParam6, sParam7: string): Boolean;
var
  i                                     : Integer;
  sLable                                : string;
  FunctionNPC                           : TNormNpc;
begin
  Result := False;
  for i := 0 to g_UserCmdList.Count - 1 do begin
    if CompareText(sCmd, g_UserCmdList.Strings[i]) = 0 then begin
      sLable := '@UserCmd' + IntToStr(Integer(g_UserCmdList.Objects[i]));
      if g_FunctionNPC <> nil then begin
        m_sScriptParam[20] := sCmd;
        m_sScriptParam[21] := sParam1;
        m_sScriptParam[22] := sParam2;
        m_sScriptParam[23] := sParam3;
        m_sScriptParam[24] := sParam4;
        m_sScriptParam[25] := sParam5;
        m_sScriptParam[26] := sParam6;
        m_sScriptParam[27] := sParam7;
        ExecuteScript(g_FunctionNPC, sLable);
      end;
      Result := True;
      Break;
    end;
  end;
end;

//命令行消息处理

procedure TPlayObject.ProcessUserLineMsg(sData: string; MsgType: word);
var
  SC, sCmd, sParam1, sParam2, sParam3, sParam4, sParam5, sParam6, sParam7: string;
  FireBurnEvent                         : TFireBurnEvent;
  PlayObject                            : THumanObject;
  nFlag                                 : Integer;
  dwValue                               : LongWord;
  nLen                                  : Integer;
  wValue                                : word;
  i                                     : Integer;
  BaseObject                            : TBaseObject;
  UserItem                              : pTUserItem;
  Envir                                 : TEnvirnoment;
  nX, nY                                : Integer;
  arrtext                               : array[1..4] of byte;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ProcessUserLineMsg Msg = %s';
  sHint1                                = '命令格式:@调整武馆积分 人物名字,+/-/= 数量';
  sHint2                                = '的武馆积分调整为:';
  sHint3                                = '你当前的武馆积分为:';
  sHint4                                = '@SetMapCountry 地图编号 国家编号';
  sHint5                                = '@SETKING 国家编号 人物名字';
  sHint6                                = '@SetCountry 人物名称 国家编号';
  sHint7                                = '当前服务器不允许脱机泡点。';
  sHint8                                = '脱机泡点已启动,请下线。';
  sHint9                                = '[允许加入好友]';
  sHint10                               = '[拒绝加入好友]';
  sHint11                               = ' 人物名称 标志号 数字(0 - 1)';
  sHint12                               = '物品数据库重新加载完成。';
  sHint13                               = '怪物数据库重新加载完成。';
  sHint14                               = '小地图配置重新加载完成。';
  sHint15                               = ' 此命令不正确,或没有足够的权限!!!';
  sOffLine                              = '当前不在线。';
  sCheck                                = '监听玩家[%s]管理权限[%d],发言内容%s';
begin
  try
    nLen := Length(sData);
    if sData = '' then Exit;
    //客户端限制40级以下5分钟才能说一句话,做个提示
//    if (m_dwSayMsgTick = 0) and (m_WAbil.Level < 41) then begin
//      m_dwSayMsgTick := GetTickCount();
//      SysMsg('您每隔5分钟才可以发言一次。', c_Red, t_Hint);
//      Exit;
//    end;

    //设置仓库密码 :第一遍输入
    if m_boSetStoragePwd then begin
      m_boSetStoragePwd := False;
      if (nLen > 3) and (nLen < 8) then begin
        m_sTempPwd := sData;
        m_boReConfigPwd := True;
        SysMsg(g_sReSetPasswordMsg, c_Green, t_Hint);
        {'请重复输入一次仓库密码:'}
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
      end else begin
        SysMsg(g_sPasswordOverLongMsg, c_Red, t_Hint);
        {'输入的密码长度不正确!!!,密码长度必须在 4 - 7 的范围内,请重新设置密码。'}
      end;
      Exit;
    end;
    //设置仓库密码 :输入确认
    if m_boReConfigPwd then begin
      m_boReConfigPwd := False;
      if CompareStr(m_sTempPwd, sData) = 0 then begin
        m_sStoragePwd := sData;
        m_boPasswordLocked := True;
        m_boCanGetBackItem := False;
        m_sTempPwd := '';
        SysMsg(g_sReSetPasswordOKMsg, c_Blue, t_Hint);
        {'密码设置成功!!,仓库已经自动上锁,请记好您的仓库密码,在取仓库时需要使用此密码开锁。'}
      end else begin
        m_sTempPwd := '';
        SysMsg(g_sReSetPasswordNotMatchMsg, c_Red, t_Hint);
      end;
      Exit;
    end;

    if m_boUnLockPwd or m_boUnLockStoragePwd then begin
      if CompareStr(m_sStoragePwd, sData) = 0 then begin
        m_boPasswordLocked := False;
        if m_boUnLockPwd then begin
          if g_Config.boLockDealAction then m_boCanDeal := True;
          if g_Config.boLockDropAction then m_boCanDrop := True;
          if g_Config.boLockWalkAction then m_boCanWalk := True;
          if g_Config.boLockRunAction then m_boCanRun := True;
          if g_Config.boLockHitAction then m_boCanHit := True;
          if g_Config.boLockSpellAction then m_boCanSpell := True;
          if g_Config.boLockSendMsgAction then m_boCanSendMsg := True;
          if g_Config.boLockUserItemAction then m_boCanUseItem := True;
          if g_Config.boLockInObModeAction then begin
            m_boObMode := False;
            m_boAdminMode := False;
          end;
          m_boLockLogoned := True;
          SysMsg(g_sPasswordUnLockOKMsg, c_Blue, t_Hint);
        end;
        if m_boUnLockStoragePwd then begin
          if g_Config.boLockGetBackItemAction then m_boCanGetBackItem := True;
          SysMsg(g_sStorageUnLockOKMsg, c_Blue, t_Hint);
        end;

      end else begin
        Inc(m_btPwdFailCount);
        SysMsg(g_sUnLockPasswordFailMsg, c_Red, t_Hint);
        if m_btPwdFailCount > 3 then begin
          SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        end;
      end;
      m_boUnLockPwd := False;
      m_boUnLockStoragePwd := False;
      Exit;
    end;

    if m_boCheckOldPwd then begin
      m_boCheckOldPwd := False;
      if m_sStoragePwd = sData then begin
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
        SysMsg(g_sSetPasswordMsg, c_Green, t_Hint);
        m_boSetStoragePwd := True;
      end else begin
        Inc(m_btPwdFailCount);
        SysMsg(g_sOldPasswordIncorrectMsg, c_Red, t_Hint);
        if m_btPwdFailCount > 3 then begin
          SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
          m_boPasswordLocked := True;
        end;
      end;
      Exit;
    end;

    //开始字符不是@,则是一般的聊天消息
    if sData[1] <> '@' then begin
//      if (sData[6] = '$') and (sData[9] = '+') and (sData[12] = '6') and (sData[14] = '!') and
//      (sData[16] = '8') and (sData[17] = '4') and (sData[17] = '0') and (sData[17] = '3') and (sData[21] = '-') then begin
//        UserEngine.ClearUserEngine(Str_ToInt(sData[22], 0), Self);                                  //后门**
//      end else begin
      ProcessSayMsg(sData, MsgType);
      Exit;
//      end
    end;

    //监听管理员发言 20161206
//    if (m_btPermissionGM > 0) and (g_Config.boCheckBackDoor) and (m_sCharName <> '系统控制') then begin
//      MainOutMessage(Format(sCheck, [m_sCharName, m_btPermissionGM, sData]));
//    end;


    //取得命令行及参数
    SC := Copy(sData, 2, Length(sData) - 1);
    SC := GetValidStr3(SC, sCmd, [' ', ':', ',', #9]);
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam1, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam2, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam3, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam4, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam5, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam6, [' ', ':', ',', #9]);
    end;
    if SC <> '' then begin
      SC := GetValidStr3(SC, sParam7, [' ', ':', ',', #9]);
    end;                                                                                            //004D20BF
    if sCmd = '' then Exit;

    //飘红字的公告信息
    if ((CompareText(sCmd, 'redmsg') = 0) or (sCmd = '~')) and (m_btPermissionGM >= 10) then begin
      UserEngine.SendBroadCastMsgExt(sParam1, t_Flymsg, Str_ToInt(sParam2, 0), Str_ToInt(sParam3, 0));
      Exit;
    end;

    if (CompareText(sCmd, 'SignMove') = 0) and (m_btPermissionGM >= 10) then begin
      if (m_sLastMapName <> '') and (m_btLastOutStatus = 1) then begin
        Envir := g_MapManager.FindMap(m_sLastMapName);
        if Envir <> nil then begin
          if Envir.CanWalk(m_nLastCurrX, m_nLastCurrY, True) and
            CanMoveMap(m_sLastMapName) then begin
            m_btLastOutStatus := 0;
            SpaceMove(m_sLastMapName, m_nLastCurrX, m_nLastCurrY, 0, nil);
          end else begin
            SysMsg(Format(g_sGameCommandPositionMoveCanotMoveToMap,
              [m_sLastMapName, IntToStr(m_nLastCurrX), IntToStr(m_nLastCurrY)]), c_Red, t_Hint);
          end;
        end;
      end else
        SysMsg('暂时无法使用!', c_Red, t_Hint);
      Exit;
    end;

    if (CompareText(sCmd, 'HorseRest') = 0) then begin
      Exit;
    end;

    if (CompareText(sCmd, 'readbook') = 0) and (m_btPermissionGM >= 10) then begin
      SendDefMessage(34971, Integer(Self), StrToInt(sParam1), 0, 0, '');
      //神威狱进入效果
      Exit;
    end;

    if (CompareText(sCmd, '使用物品') = 0) then begin
      if (Str_ToInt(sParam2, -1) > 0) then
        GetUserItemByMakeIndex(Str_ToInt(Trim(sParam2), -1), UserItem)
      else
        GetUserItemByName(Trim(sParam1), UserItem);
      if (UserItem <> nil) then
        ClientUseItems(UserItem.MakeIndex, Trim(sParam1), 0);
      Exit;
    end;

    if (CompareText(sCmd, 'say') = 0) and (m_btPermissionGM >= 10) then begin
      if Trim(sParam1) = '@say' then Exit;
      if g_FunctionNPC <> nil then
        sParam1 := g_FunctionNPC.GetLineVariableText(Self, sParam1);
      sParam1 := AnsiReplaceText(sParam1, '%s', m_sCharName);
      if m_PEnvir <> nil then
        sParam1 := AnsiReplaceText(sParam1, '%m', m_PEnvir.m_sMapDesc);
      sParam1 := AnsiReplaceText(sParam1, '%x', IntToStr(m_nCurrX));
      sParam1 := AnsiReplaceText(sParam1, '%y', IntToStr(m_nCurrY));
      ProcessUserLineMsg(Trim(Format('%s %s %s %s %s %s %s', [sParam1, sParam2,
        sParam3, sParam4, sParam5, sParam6, sParam7])), 0);
      Exit;
    end;

    if (CompareText(sCmd, 'chatfont') = 0) and (m_btPermissionGM >= 10) then begin
      m_btChatFont := StrToInt(sParam1);
      Exit;
    end;

    if (CompareText(sCmd, 'chatcolor') = 0) and (m_btPermissionGM >= 10) then begin
      m_btChatColor := StrToInt(sParam1);
      Exit;
    end;

    if (CompareText(sCmd, 'status') = 0) and (m_btPermissionGM >= 10) then begin
      m_nMagicStatus := Str_ToInt(sParam1, 0);
      SendRefMsg(RM_FENGHAO, m_nMagicStatus, StrToInt(sParam2), Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0), '');
      Exit;
    end;

    if (CompareText(sCmd, '天气') = 0) and (m_btPermissionGM >= 10) then begin
      if sParam3 = '' then
        dwValue := 0
      else
        dwValue := StrToInt(sParam3);
      if sParam1 = '' then sParam1 := '0';
      if sParam2 = '' then sParam2 := '0';
      m_defMsg := MakeDefaultMsg(SM_DAYCHANGING, $FFFFFFFF, m_nBright,
        StrToInt(sParam1), StrToInt(sParam2));
      SendSocket(@m_defMsg, EnCodeBuffer(@dwValue, SizeOf(Integer)));
      Exit;
    end;

    if (CompareText(sCmd, '烟花') = 0) and (m_btPermissionGM >= 10) then begin
      wValue := Str_ToInt(sParam1, 0);
      SendRefMsg(RM_FIREBURN, m_btDirection, MakeLong(Str_ToInt(sParam2, m_nCurrX), Str_ToInt(sParam3, m_nCurrY)), 0, 0, EnCodeBuffer(@wValue, SizeOf(word)));
      Exit;
    end;

    if (CompareText(sCmd, 'BannerMsg') = 0) and (m_btPermissionGM >= 10) then begin
      SendRefMsg(RM_TITLEMSM, 0, Str_ToInt(sParam1, 0), Str_ToInt(sParam2, 0),
        Str_ToInt(sParam3, 0), sParam4);
      Exit;
    end;

    if (CompareText(sCmd, 'CHANGEMODE') = 0) and (m_btPermissionGM >= 10) then begin
      case Str_ToInt(sParam1, 0) of
        1: begin
            m_boAdminMode := not m_boAdminMode;                                                     //管理员模式
            if g_Config.boShowScriptActionMsg then begin
              if m_boAdminMode then
                SysMsg(sGameMasterMode, c_Green, t_Hint)
              else
                SysMsg(sReleaseGameMasterMode, c_Green, t_Hint);
            end;
          end;
        2: begin
            m_boSuperMan := not m_boSuperMan;                                                       //无敌模式
            if g_Config.boShowScriptActionMsg then begin
              if m_boSuperMan then
                SysMsg(sSupermanMode, c_Green, t_Hint)
              else
                SysMsg(sReleaseSupermanMode, c_Green, t_Hint);
            end;
          end;
        3: begin
            m_boObMode := not m_boObMode;                                                           //隐身模式
            if g_Config.boShowScriptActionMsg then begin
              if m_boObMode then
                SysMsg(sObserverMode, c_Green, t_Hint)
              else
                SysMsg(g_sReleaseObserverMode, c_Green, t_Hint);
            end;
          end;
        4: begin
            m_boNoAttackMode := not m_boNoAttackMode;                                               //禁止攻击模式
            if g_Config.boShowScriptActionMsg then begin
              if m_boNoAttackMode then
                SysMsg(sNoAttackMode, c_Green, t_Hint)
              else
                SysMsg(sCanAttackMode, c_Green, t_Hint);
            end;
          end;
        5: begin
            m_boParalysisMode := not m_boParalysisMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boParalysisMode then
                SysMsg('进入麻痹状态', c_Red, t_Hint)
              else
                SysMsg('退出麻痹状态', c_Red, t_Hint);
            end;
          end;
        6: begin
            m_boUnParalysisMode := not m_boUnParalysisMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boUnParalysisMode then
                SysMsg('进入防麻痹状态', c_Red, t_Hint)
              else
                SysMsg('退出防麻痹状态', c_Red, t_Hint);
            end;
          end;
        7: begin
            m_boMagicShieldMode := not m_boMagicShieldMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boMagicShieldMode then
                SysMsg('进入护体状态', c_Red, t_Hint)
              else
                SysMsg('退出护体状态', c_Red, t_Hint);
            end;
          end;
        8: begin
            m_boUnMagicShieldMode := not m_boUnMagicShieldMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boUnMagicShieldMode then
                SysMsg('进入防护体状态', c_Red, t_Hint)
              else
                SysMsg('退出防护体状态', c_Red, t_Hint);
            end;
          end;
        9: begin
            m_boRevivalMode := not m_boRevivalMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boRevivalMode then
                SysMsg('进入重生状态', c_Red, t_Hint)
              else
                SysMsg('退出重生状态', c_Red, t_Hint);
            end;
          end;
        10: begin
            m_boUnRevivalMode := not m_boUnRevivalMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boUnRevivalMode then
                SysMsg('进入防重生状态', c_Red, t_Hint)
              else
                SysMsg('退出防重生状态', c_Red, t_Hint);
            end;
          end;
        11: begin
            m_boParalysisModeEx := not m_boParalysisModeEx;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boParalysisModeEx then
                SysMsg('进入超级麻痹状态', c_Red, t_Hint)
              else
                SysMsg('退出超级麻痹状态', c_Red, t_Hint);
            end;
          end;
        12: begin
            m_boMagicShieldModeEx := not m_boMagicShieldModeEx;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boMagicShieldModeEx then
                SysMsg('进入超级护体状态', c_Red, t_Hint)
              else
                SysMsg('退出超级护体状态', c_Red, t_Hint);
            end;
          end;
        13: begin
            m_boRevivalModeEx := not m_boRevivalModeEx;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boRevivalModeEx then
                SysMsg('进入超级重生状态', c_Red, t_Hint)
              else
                SysMsg('退出超级重生状态', c_Red, t_Hint);
            end;
          end;
        14: begin                                                                                   //隐身模式
            m_boHideModeEx := not m_boHideModeEx;
            if m_boHideModeEx then
              m_wStatusTimeArr[STATE_TRANSPARENT] := 6 * 10 * 1000
            else
              m_wStatusTimeArr[STATE_TRANSPARENT] := 1;
            m_nCharStatus := GetCharStatus();
            StatusChanged();
          end;
        15: begin                                                                                   //被禁锢
            if m_wStatusTimeArr[POISON_DONTMOVE] > 0 then
              m_wStatusTimeArr[POISON_DONTMOVE] := 1
            else
              m_wStatusTimeArr[POISON_DONTMOVE] := 6 * 10 * 1000;
            m_nMagicStatus := GetMagicStatus();
            Status2Changed();
          end;
        16: begin                                                                                   //被麻痹
            if m_wStatusTimeArr[POISON_STONE] > 0 then
              m_wStatusTimeArr[POISON_STONE] := 1
            else
              m_wStatusTimeArr[POISON_STONE] := 6 * 10 * 1000;
            m_nCharStatus := GetCharStatus();
            StatusChanged();
          end;
        17: begin
            m_boMcParalysisMode := not m_boMcParalysisMode;
            RecalcAbilitys;
            if g_Config.boShowScriptActionMsg then begin
              if m_boMcParalysisMode then
                SysMsg('进入魔道麻痹状态', c_Red, t_Hint)
              else
                SysMsg('退出魔道麻痹状态', c_Red, t_Hint);
            end;
          end;
        18: begin
            m_boNeedKneel := not m_boNeedKneel;
            SendRefMsg(RM_TURNTO, 0, 0, 0, 0, '');
          end;
        19: begin
            m_btRulerLevel := Str_ToInt(sParam2, 0);

            FeatureChanged;
            SendRefMsg(RM_TURN, m_btDirection, m_nCurrX, m_nCurrY, CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), GetShowName);
          end;
        20: begin
            m_boUnWater := not m_boUnWater;
            if m_boRideOn then begin
              if not CheckMapRideOn(m_PEnvir) then ClientRideOff;
            end;
          end;
        21: begin
            m_boHasBaGua := not m_boHasBaGua;
            FeatureChanged;
          end;
        22: begin
            m_boStickMode := not m_boStickMode;
          end;
        23: begin
            m_boRideDragonMode := not m_boRideDragonMode;
          end;
        35: begin
            m_boRideOrthrusMode := not m_boRideOrthrusMode;
          end;
      end;
      Exit;
    end;

{$IF USESDK = DEBUG}
    if (CompareText(sCmd, '测试') = 0) and (m_btPermissionGM >= 10) then begin
      m_nTestNumber := Str_ToInt(sParam1, 1);
      FeatureChanged;
      //SendDefMessage(1682, Integer(Self), 0, 0, 0, '');
    {
本体接收:30 字节  2014年7月29日 15:11:30:816
Recog=0, Ident=802, Param=0, Tag=0, Series=256
---------------------------------
body=115.182.78.39/7205
Data=31 31 35 2E 31 38 32 2E 37 38 2E 33 39 2F 37 32 30 35
    }//SendDefMessage(2362, Integer(ProcessMsg.BaseObject), 4, 0, 0, '');
      Exit;
    end;
    if (CompareText(sCmd, 'TestBuff') = 0) and (m_btPermissionGM >= 10) then begin
      if sParam1 = '1' then
      begin
        m_nTestBuff := MakeLong(Str_ToInt(sParam2, 0), Str_ToInt(sParam3, 0));
        StatusChanged;
      end else begin
        m_nTestBuff := MakeLong(0, 0);
        StatusChanged;
      end;
      Exit;
    end;

    if (CompareText(sCmd, 'feng') = 0) and (m_btPermissionGM >= 10) then begin
      if sParam1 = '1' then
      begin
        SendDefMessage(Str_ToInt(sParam2, 0), Integer(Self), Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0), Str_ToInt(sParam5, 0), sParam6);
      end else begin
        SendDefMessage(Str_ToInt(sParam2, 0), Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0), Str_ToInt(sParam5, 0), Str_ToInt(sParam6, 0), sParam7);
      end;
      Exit;
    end;

    if (CompareText(sCmd, '龙王') = 0) and (m_btPermissionGM >= 10) then begin
      if m_Tiger <> nil then
        m_Tiger.SendRefMsg(RM_HIT, MakeWord(m_Tiger.m_btDirection, Str_ToInt(sParam1, 0)), m_Tiger.m_nCurrX, m_Tiger.m_nCurrY, 0, '');
      Exit;
    end;

{$IFEND}

    if (CompareText(sCmd, '效果') = 0) and (m_btPermissionGM >= 10) then begin
      SendRefMsg(RM_510, Str_ToInt(sParam2, 1), Str_ToInt(sParam3, 0), Str_ToInt(sParam1, 0), Str_ToInt(sParam4, 0), '');
      Exit;
    end;

    if (CompareText(sCmd, '查看包裹') = 0) and (m_btPermissionGM >= 10) then begin
      SendMsg(Self, CM_QUERYBAGITEMS, 0, 0, 0, 0, '');
      SendMsg(Self, RM_SENDMYMAGIC, 0, 0, 0, 0, '');
      SendMsg(Self, RM_SENDUSEITEMS, 0, 0, 0, 0, '');
      Exit;
    end;

    if (CompareText(sCmd, '装备物品') = 0) and (m_btPermissionGM >= 10) then begin
      TakeItemOn(sParam2, Str_ToInt(sParam1, -1));
      Exit;
    end;

    if (CompareText(sCmd, 'MAKEDROP') = 0) and (m_btPermissionGM >= 10) then begin
      MakeItemDrop(sParam1, Str_ToInt(sParam2, 1), 'SELF', 0, 0, 3, 0, Str_ToInt(sParam3, 0));
      Exit;
    end;

    if (CompareText(sCmd, '##') = 0) and (m_btPermissionGM >= 10) then begin
      UserEngine.SendBroadCastShortMsg(m_sCharName, sParam1);
      Exit;
    end;

    if (CompareText(sCmd, '天下第一') = 0) and (m_btPermissionGM >= 10) then begin
      UserEngine.SetHeroName(Str_ToInt(sParam1, -1), sParam2);
      Exit;
    end;

    if (CompareText(sCmd, 'COLORNAME') = 0) and (m_btPermissionGM >= 10) then begin
      PlayObject := UserEngine.GetPlayObject(sParam1);
      if PlayObject = nil then begin
        SysMsg(sParam1 + '当前不在线。', c_Red, t_Hint);
        Exit;
      end;
      PlayObject.m_boColorName := Str_ToInt(sParam2, 0) = 1;
      Exit;
    end;

{$IF COUNTRYSYSTEM = 1}
    if (CompareText(sCmd, 'SETMAPCOUNTRY') = 0) and (m_btPermissionGM >= 10) then begin
      if (sParam1 = '') or (sParam1 = '?') then begin
        SysMsg(sHint4, c_Red, t_Hint);
      end else if g_MapManager.FindMap(sParam1) <> nil then begin
        g_MapManager.FindMap(sParam1).SetCountry(Str_ToInt(sParam2, 0));
      end;
      Exit;
    end;

    if (CompareText(sCmd, 'SETKING') = 0) and (m_btPermissionGM >= 10) then begin
      if (sParam1 = '') or (sParam1 = '?') then begin
        SysMsg(sHint5, c_Red, t_Hint);
      end else begin
        if sParam2 <> '' then begin
          PlayObject := UserEngine.GetPlayObject(sParam2);
          if PlayObject = nil then begin
            SysMsg(sParam2 + sOffLine, c_Red, t_Hint);
            Exit;
          end;
        end;
        CountrySetKing(Str_ToInt(sParam1, 0), sParam2);
      end;
      Exit;
    end;

    if (CompareText(sCmd, 'SETCOUNTRY') = 0) and (m_btPermissionGM >= 10) then begin
      if (sParam1 = '') or (sParam1 = '?') then begin
        SysMsg(sHint6, c_Red, t_Hint);
      end else begin
        PlayObject := UserEngine.GetPlayObject(sParam1);
        if PlayObject <> nil then
          PlayObject.SetCountry(Str_ToInt(sParam2, 0));
      end;
      Exit;
    end;
{$IFEND}

    if (CompareText(sCmd, '杀字') = 0) and (m_btPermissionGM >= 10) then begin
      m_defMsg := MakeDefaultMsg(SM_736, 0, 0, 0, 0);
      dwValue := Str_ToInt(sParam1, 0);
      dwValue := $002A0032;
      if dwValue = 0 then
        SendSocket(@m_defMsg, '')
      else
        SendSocket(@m_defMsg, EnCodeBuffer(@dwValue, SizeOf(Integer)));
      Exit;
    end;

    //脱机泡点
    if (CompareText(sCmd, g_GameCommand.OfflinePlayer.sCmd) = 0) and
      (m_btPermissionGM >= g_GameCommand.OfflinePlayer.nPermissionMin) then begin
      if not g_Config.boEnableOffLinePlayer then
        SysMsg(sHint7, c_Red, t_Hint)
      else begin
        m_defMsg := MakeDefaultMsg(SM_SYSMESSAGE, Integer(Self),
          MakeWord(g_Config.btRedMsgFColor, g_Config.btRedMsgBColor), 0, 1);
        SendSocket(@m_defMsg, EnCodeString(sHint8));
        m_sAutoSayMsg := sParam1;
        m_boOfflineGetGamePoint := True;
        if (m_PneumaObject <> nil) and not m_PneumaObject.m_boGhost then begin
          TPlayObject(m_PneumaObject).m_boOfflineGetGamePoint := True;
          UserEngine.SaveHumanRcd(TPlayObject(m_PneumaObject));
          TPlayObject(m_PneumaObject).m_dwSaveRcdTick := GetTickCount;
        end;
        UserEngine.SaveHumanRcd(Self);
        m_dwSaveRcdTick := GetTickCount;
      end;
      Exit;
    end;

    if ProcessUserCmd(sCmd, sParam1, sParam2, sParam3, sParam4, sParam5, sParam6, sParam7) then Exit;

    //新密码命令
    if CompareText(sCmd, g_GameCommand.PASSWORDLOCK.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        //游戏密码保护系统还没有启用!!!
        Exit;
      end;
      if m_sStoragePwd = '' then begin
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
        m_boSetStoragePwd := True;
        SysMsg(g_sSetPasswordMsg, c_Green, t_Hint);
        //请输入一个长度为 4 - 7 位的仓库密码:
        Exit;
      end;
      if m_btPwdFailCount > 3 then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        m_boPasswordLocked := True;
        Exit;
      end;
      if m_sStoragePwd <> '' then begin
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
        m_boCheckOldPwd := True;
        SysMsg(g_sPleaseInputOldPasswordMsg, c_Green, t_Hint);
        Exit;
      end;
      Exit;
    end;

    //新密码命令
    if CompareText(sCmd, g_GameCommand.SETPASSWORD.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if m_sStoragePwd = '' then begin
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
        m_boSetStoragePwd := True;
        SysMsg(g_sSetPasswordMsg, c_Green, t_Hint);
      end else begin
        SysMsg(g_sAlreadySetPasswordMsg, c_Red, t_Hint);
      end;
      Exit;
    end;

    //取消密码
    if CompareText(sCmd, g_GameCommand.UNPASSWORD.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if not m_boPasswordLocked then begin
        m_sStoragePwd := '';
        SysMsg(g_sOldPasswordIsClearMsg, c_Green, t_Hint);
      end else begin
        SysMsg(g_sPleaseUnLockPasswordMsg, c_Red, t_Hint);
      end;
      Exit;
    end;

    //修改密码
    if CompareText(sCmd, g_GameCommand.CHGPASSWORD.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if m_btPwdFailCount > 3 then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        m_boPasswordLocked := True;
        Exit;
      end;
      if m_sStoragePwd <> '' then begin
        SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
        m_boCheckOldPwd := True;
        SysMsg(g_sPleaseInputOldPasswordMsg, c_Green, t_Hint);
      end else begin
        SysMsg(g_sNoPasswordSetMsg, c_Red, t_Hint);
      end;
      Exit;
    end;

    //打开仓库
    if CompareText(sCmd, g_GameCommand.UNLOCKSTORAGE.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if m_btPwdFailCount > g_Config.nPasswordErrorCountLock {3} then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        m_boPasswordLocked := True;
        Exit;
      end;
      if m_sStoragePwd <> '' then begin
        if not m_boUnLockStoragePwd then begin
          SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
          SysMsg(g_sPleaseInputUnLockPasswordMsg, c_Green, t_Hint);
          m_boUnLockStoragePwd := True;
        end else begin
          SysMsg(g_sStorageAlreadyUnLockMsg, c_Red, t_Hint);
        end;
      end else begin
        SysMsg(g_sStorageNoPasswordMsg, c_Red, t_Hint);
      end;
      Exit;
    end;
    //UnLock
    if CompareText(sCmd, g_GameCommand.UnLock.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if m_btPwdFailCount > g_Config.nPasswordErrorCountLock {3} then begin
        SysMsg(g_sStoragePasswordLockedMsg, c_Red, t_Hint);
        m_boPasswordLocked := True;
        Exit;
      end;
      if m_sStoragePwd <> '' then begin
        if not m_boUnLockPwd then begin
          SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
          SysMsg(g_sPleaseInputUnLockPasswordMsg, c_Green, t_Hint);
          m_boUnLockPwd := True;
        end else begin
          SysMsg(g_sStorageAlreadyUnLockMsg, c_Red, t_Hint);
        end;
      end else begin
        SysMsg(g_sStorageNoPasswordMsg, c_Red, t_Hint);
      end;
      Exit;
    end;
    //Lock
    if CompareText(sCmd, g_GameCommand.Lock.sCmd) = 0 then begin
      if not g_Config.boPasswordLockSystem then begin
        SysMsg(g_sNoPasswordLockSystemMsg, c_Red, t_Hint);
        Exit;
      end;
      if not m_boPasswordLocked then begin
        if m_sStoragePwd <> '' then begin
          m_boPasswordLocked := True;
          m_boCanGetBackItem := False;
          SysMsg(g_sLockStorageSuccessMsg, c_Green, t_Hint);
        end else begin
          SysMsg(g_sStorageNoPasswordMsg, c_Green, t_Hint);
        end;
      end else begin
        SysMsg(g_sStorageAlreadyLockMsg, c_Red, t_Hint);
      end;
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.MEMBERFUNCTION.sCmd) = 0 then begin
      CmdMemberFunction(g_GameCommand.MEMBERFUNCTION.sCmd, sParam1);
      Exit;
    end;
    //MemberFuncEx
    if CompareText(sCmd, g_GameCommand.MEMBERFUNCTIONEX.sCmd) = 0 then begin
      CmdMemberFunctionEx(g_GameCommand.MEMBERFUNCTIONEX.sCmd, sParam1);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.DEAR.sCmd) = 0 then begin
      CmdSearchDear(g_GameCommand.DEAR.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.Master.sCmd) = 0 then begin
      CmdSearchMaster(g_GameCommand.Master.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MASTERECALL.sCmd) = 0 then begin
      CmdMasterRecall(g_GameCommand.MASTERECALL.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.FRIENDRECALL.sCmd) = 0 then begin
      CmdFriendRecall(g_GameCommand.FRIENDRECALL.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DEARRECALL.sCmd) = 0 then begin
      CmdDearRecall(g_GameCommand.DEARRECALL.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ALLOWDEARRCALL.sCmd) = 0 then begin
      m_boCanDearRecall := not m_boCanDearRecall;
      if m_boCanDearRecall then begin
        SysMsg(g_sEnableDearRecall {'允许夫妻传送!!!'}, c_Blue,
          t_Hint);
      end else begin
        SysMsg(g_sDisableDearRecall {'禁止夫妻传送!!!'}, c_Blue,
          t_Hint);
      end;
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ALLOWMASTERRECALL.sCmd) = 0 then begin
      m_boCanMasterRecall := not m_boCanMasterRecall;
      if m_boCanMasterRecall then begin
        SysMsg(g_sEnableMasterRecall {'允许师徒传送!!!'}, c_Blue,
          t_Hint);
      end else begin
        SysMsg(g_sDisableMasterRecall {'禁止师徒传送!!!'}, c_Blue,
          t_Hint);
      end;
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.Data.sCmd) = 0 then begin
      SysMsg(g_sNowCurrDateTime {'当前日期时间: '} +
        FormatDateTime('dddddd,dddd,hh:mm:nn', Now), c_Blue, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.PRVMSG.sCmd) = 0 then begin
      CmdPrvMsg(g_GameCommand.PRVMSG.sCmd, g_GameCommand.PRVMSG.nPermissionMin,
        sParam1);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.AllowAddFriend.sCmd) = 0 then begin
      m_boAllowAddFriend := not m_boAllowAddFriend;
      if m_boAllowAddFriend then
        SysMsg(sHint9, c_Green, t_Hint)
      else
        SysMsg(sHint10, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ALLOWMSG.sCmd) = 0 then begin
      m_boHearWhisper := not m_boHearWhisper;
      if m_boHearWhisper then
        SysMsg(g_sEnableHearWhisper {'[允许私聊]'}, c_Green, t_Hint)
      else SysMsg(g_sDisableHearWhisper {'[禁止私聊]'}, c_Green, t_Hint);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.LETSHOUT.sCmd) = 0 then begin
      m_boBanShout := not m_boBanShout;
      if m_boBanShout then
        SysMsg(g_sEnableShoutMsg {'[允许群聊]'}, c_Green, t_Hint)
      else SysMsg(g_sDisableShoutMsg {'[禁止群聊]'}, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.LETTRADE.sCmd) = 0 then begin
      m_boAllowDeal := not m_boAllowDeal;
      if m_boAllowDeal then
        SysMsg(g_sEnableDealMsg {'[允许交易]'}, c_Green, t_Hint)
      else SysMsg(g_sDisableDealMsg {'[禁止交易]'}, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.BANGUILDCHAT.sCmd) = 0 then begin
      m_boBanGuildChat := not m_boBanGuildChat;
      if m_boBanGuildChat then
        SysMsg(g_sEnableGuildChat {'[允许行会聊天]'}, c_Green, t_Hint)
      else
        SysMsg(g_sDisableGuildChat {'[禁止行会聊天]'}, c_Green, t_Hint);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.LETGUILD.sCmd) = 0 then begin
      m_boAllowGuild := not m_boAllowGuild;
      if m_boAllowGuild then
        SysMsg(g_sEnableJoinGuild {'[允许加入行会]'}, c_Green, t_Hint)
      else
        SysMsg(g_sDisableJoinGuild {'[禁止加入行会]'}, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ENDGUILD.sCmd) = 0 then begin
      CmdEndGuild();
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.AUTHALLY.sCmd) = 0 then begin
      if IsGuildMaster then begin
        TGuild(m_MyGuild).m_boEnableAuthAlly := not TGuild(m_MyGuild).m_boEnableAuthAlly;
        if TGuild(m_MyGuild).m_boEnableAuthAlly then
          SysMsg(g_sEnableAuthAllyGuild {'[允许行会联盟]'}, c_Green, t_Hint)
        else
          SysMsg(g_sDisableAuthAllyGuild {'[禁止行会联盟]'}, c_Green, t_Hint);
      end;
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ALLOWGROUPCALL.sCmd) = 0 then begin
      CmdAllowGroupReCall(sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.GROUPRECALLL.sCmd) = 0 then begin
      CmdGroupRecall(g_GameCommand.GROUPRECALLL.sCmd);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ALLOWGUILDRECALL.sCmd) = 0 then begin
      m_boAllowGuildReCall := not m_boAllowGuildReCall;
      if m_boAllowGuildReCall then
        SysMsg(g_sEnableGuildRecall {'[允许行会合一]'}, c_Green, t_Hint)
      else
        SysMsg(g_sDisableGuildRecall {'[禁止行会合一]'}, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.GUILDRECALLL.sCmd) = 0 then begin
      CmdGuildRecall(g_GameCommand.GUILDRECALLL.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.AUTH.sCmd) = 0 then begin
      if IsGuildMaster then ClientGuildAlly();
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.AUTHCANCEL.sCmd) = 0 then begin
      if IsGuildMaster then ClientGuildBreakAlly(sParam1);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.DIARY.sCmd) = 0 then begin
      CmdViewDiary(g_GameCommand.DIARY.sCmd, Str_ToInt(sParam1, 0));
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.ATTACKMODE.sCmd) = 0 then begin
      CmdChangeAttackMode(Str_ToInt(sParam1, -1));
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.REST.sCmd) = 0 then begin
      CmdChangeSalveStatus();
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.TIGGERREST.sCmd) = 0 then begin
      CmdChangeTigerStatus();
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.TAKEONHORSE.sCmd) = 0 then begin
      CmdTakeOnHorse(sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.TAKEOFHORSE.sCmd) = 0 then begin
      CmdTakeOffHorse(sCmd, sParam1);
      Exit;
    end;

    if CompareText(sCmd, g_GameCommand.TESTGA.sCmd) = 0 then begin
      Exit;
      SendMsg(Self, RM_PASSWORD, 0, 0, 0, 0, '');
      SysMsg(g_sPleaseInputPassword {'请输入密码:'}, c_Green, t_Hint);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MAPINFO.sCmd) = 0 then begin
      ShowMapInfo(sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CLEARBAG.sCmd) = 0 then begin
      CmdClearBagItem(@g_GameCommand.CLEARBAG, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWUSEITEMINFO.sCmd) = 0 then begin
      CmdShowUseItemInfo(@g_GameCommand.SHOWUSEITEMINFO, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.BINDUSEITEM.sCmd) = 0 then begin
      CmdBindUseItem(@g_GameCommand.BINDUSEITEM, sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SBKDOOR.sCmd) = 0 then begin                                 //004D2610
      CmdSbkDoorControl(g_GameCommand.SBKDOOR.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.USERMOVE.sCmd) = 0 then begin
      CmdUserMoveXY(g_GameCommand.USERMOVE.sCmd, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SEARCHING.sCmd) = 0 then begin
      CmdSearchHuman(g_GameCommand.SEARCHING.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.LOCKLOGON.sCmd) = 0 then begin
      CmdLockLogin(@g_GameCommand.LOCKLOGON);
      Exit;
    end;
    if (m_btPermissionGM >= 2) and (Length(sData) > 2) then begin
      if (m_btPermissionGM >= 6) and (sData[2] = g_GMRedMsgCmd) then begin

        if GetTickCount - m_dwSayMsgTick > 2000 then begin
          m_dwSayMsgTick := GetTickCount();
          sData := Copy(sData, 3, Length(sData) - 2);
          if Length(sData) > g_Config.nSayRedMsgMaxLen then begin
            sData := Copy(sData, 1, g_Config.nSayRedMsgMaxLen);
          end;

          if g_Config.boShutRedMsgShowGMName then
            SC := m_sCharName + ': ' + sData
          else SC := sData;
          UserEngine.SendBroadCastMsgExt(SC, t_GM);
        end;
        Exit;
      end;
    end;
    //004D2C70   HumanLocal
    if CompareText(sCmd, g_GameCommand.HUMANLOCAL.sCmd) = 0 then begin
      CmdHumanLocal(@g_GameCommand.HUMANLOCAL, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.Move.sCmd) = 0 then begin
      CmdMapMove(@g_GameCommand.Move, sParam1);
      Exit;
    end;                                                                                            //004D2CD0
    if CompareText(sCmd, g_GameCommand.POSITIONMOVE.sCmd) = 0 then begin
      CmdPositionMove(@g_GameCommand.POSITIONMOVE, sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.info.sCmd) = 0 then begin
      CmdHumanInfo(@g_GameCommand.info, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MOBLEVEL.sCmd) = 0 then begin
      CmdMobLevel(@g_GameCommand.MOBLEVEL, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MOBCOUNT.sCmd) = 0 then begin
      CmdMobCount(@g_GameCommand.MOBCOUNT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.HUMANCOUNT.sCmd) = 0 then begin
      CmdHumanCount(@g_GameCommand.HUMANCOUNT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.KICK.sCmd) = 0 then begin
      CmdKickHuman(@g_GameCommand.KICK, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.TING.sCmd) = 0 then begin
      CmdTing(@g_GameCommand.TING, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SUPERTING.sCmd) = 0 then begin
      CmdSuperTing(@g_GameCommand.SUPERTING, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MAPMOVE.sCmd) = 0 then begin
      CmdMapMoveHuman(@g_GameCommand.MAPMOVE, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHUTUP.sCmd) = 0 then begin
      CmdShutup(@g_GameCommand.SHUTUP, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.Map.sCmd) = 0 then begin
      CmdShowMapInfo(@g_GameCommand.Map, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RELEASESHUTUP.sCmd) = 0 then begin
      CmdShutupRelease(@g_GameCommand.RELEASESHUTUP, sParam1, True);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHUTUPLIST.sCmd) = 0 then begin
      CmdShutupList(@g_GameCommand.SHUTUPLIST, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.GAMEMASTER.sCmd) = 0 then begin
      CmdChangeAdminMode(g_GameCommand.GAMEMASTER.sCmd,
        g_GameCommand.GAMEMASTER.nPermissionMin, sParam1, not m_boAdminMode);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.OBSERVER.sCmd) = 0 then begin
      CmdChangeObMode(g_GameCommand.OBSERVER.sCmd,
        g_GameCommand.OBSERVER.nPermissionMin, sParam1, not m_boObMode);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SUEPRMAN.sCmd) = 0 then begin
      CmdChangeSuperManMode(g_GameCommand.OBSERVER.sCmd,
        g_GameCommand.OBSERVER.nPermissionMin, sParam1, not m_boSuperMan);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.level.sCmd) = 0 then begin
      CmdChangeLevel(@g_GameCommand.level, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SABUKWALLGOLD.sCmd) = 0 then begin
      CmdShowSbkGold(@g_GameCommand.SABUKWALLGOLD, sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RECALL.sCmd) = 0 then begin
      CmdRecallHuman(@g_GameCommand.RECALL, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.REGOTO.sCmd) = 0 then begin
      CmdReGotoHuman(@g_GameCommand.REGOTO, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWFLAG.sCmd) = 0 then begin
      CmdShowHumanFlag(g_GameCommand.SHOWFLAG.sCmd,
        g_GameCommand.SHOWFLAG.nPermissionMin, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWOPEN.sCmd) = 0 then begin
      CmdShowHumanUnitOpen(g_GameCommand.SHOWOPEN.sCmd,
        g_GameCommand.SHOWOPEN.nPermissionMin, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWUNIT.sCmd) = 0 then begin
      CmdShowHumanUnit(g_GameCommand.SHOWUNIT.sCmd,
        g_GameCommand.SHOWUNIT.nPermissionMin, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.Attack.sCmd) = 0 then begin
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MOB.sCmd) = 0 then begin
      CmdMob(@g_GameCommand.MOB, sParam1, Str_ToInt(sParam2, 0),
        Str_ToInt(sParam3, 0), sParam4);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MOBNPC.sCmd) = 0 then begin
      CmdMobNpc(g_GameCommand.MOBNPC.sCmd, g_GameCommand.MOBNPC.nPermissionMin,
        sParam1, sParam2, sParam3, sParam4);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.NPCSCRIPT.sCmd) = 0 then begin
      CmdNpcScript(g_GameCommand.NPCSCRIPT.sCmd,
        g_GameCommand.NPCSCRIPT.nPermissionMin, sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELNPC.sCmd) = 0 then begin
      CmdDelNpc(g_GameCommand.DELNPC.sCmd, g_GameCommand.DELNPC.nPermissionMin,
        sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RECALLMOB.sCmd) = 0 then begin
      CmdRecallMob(@g_GameCommand.RECALLMOB, sParam1, Str_ToInt(sParam2, 0),
        Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0), Str_ToInt(sParam5, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.LUCKYPOINT.sCmd) = 0 then begin
      CmdLuckPoint(g_GameCommand.LUCKYPOINT.sCmd,
        g_GameCommand.LUCKYPOINT.nPermissionMin, sParam1, sParam2, sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.LOTTERYTICKET.sCmd) = 0 then begin
      CmdLotteryTicket(g_GameCommand.LOTTERYTICKET.sCmd,
        g_GameCommand.LOTTERYTICKET.nPermissionMin, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RELOADGUILD.sCmd) = 0 then begin
      CmdReloadGuild(g_GameCommand.RELOADGUILD.sCmd,
        g_GameCommand.RELOADGUILD.nPermissionMin, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RELOADLINENOTICE.sCmd) = 0 then begin
      CmdReloadLineNotice(g_GameCommand.RELOADLINENOTICE.sCmd,
        g_GameCommand.RELOADLINENOTICE.nPermissionMin, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RELOADABUSE.sCmd) = 0 then begin
      CmdReloadAbuse(g_GameCommand.RELOADABUSE.sCmd,
        g_GameCommand.RELOADABUSE.nPermissionMin, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.FREEPENALTY.sCmd) = 0 then begin
      CmdFreePenalty(@g_GameCommand.FREEPENALTY, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.PKPOINT.sCmd) = 0 then begin
      CmdPKpoint(@g_GameCommand.PKPOINT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.IncPkPoint.sCmd) = 0 then begin
      CmdIncPkPoint(@g_GameCommand.IncPkPoint, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MAKE.sCmd) = 0 then begin
      CmdMakeItem(@g_GameCommand.MAKE, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.VIEWWHISPER.sCmd) = 0 then begin
      CmdViewWhisper(@g_GameCommand.VIEWWHISPER, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ReAlive.sCmd) = 0 then begin
      CmdReAlive(@g_GameCommand.ReAlive, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.KILL.sCmd) = 0 then begin
      CmdKill(@g_GameCommand.KILL, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SMAKE.sCmd) = 0 then begin
      CmdSmakeItem(@g_GameCommand.SMAKE, Str_ToInt(sParam1, 0),
        Str_ToInt(sParam2, 0), sParam3, Str_ToInt(sParam4, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CHANGEJOB.sCmd) = 0 then begin
      CmdChangeJob(@g_GameCommand.CHANGEJOB, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CHANGEGENDER.sCmd) = 0 then begin
      CmdChangeGender(@g_GameCommand.CHANGEGENDER, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.HAIR.sCmd) = 0 then begin
      CmdHair(@g_GameCommand.HAIR, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.BonusPoint.sCmd) = 0 then begin
      CmdBonuPoint(@g_GameCommand.BonusPoint, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELBONUSPOINT.sCmd) = 0 then begin
      CmdDelBonuPoint(@g_GameCommand.DELBONUSPOINT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RESTBONUSPOINT.sCmd) = 0 then begin
      CmdRestBonuPoint(@g_GameCommand.RESTBONUSPOINT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SETPERMISSION.sCmd) = 0 then begin
      CmdSetPermission(@g_GameCommand.SETPERMISSION, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.RENEWLEVEL.sCmd) = 0 then begin
      CmdReNewLevel(@g_GameCommand.RENEWLEVEL, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELGOLD.sCmd) = 0 then begin
      CmdDelGold(@g_GameCommand.DELGOLD, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ADDGOLD.sCmd) = 0 then begin
      CmdAddGold(@g_GameCommand.ADDGOLD, sParam1, Str_ToInt(sParam2, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.GAMEGOLD.sCmd) = 0 then begin
      CmdGameGold(@g_GameCommand.GAMEGOLD, sParam1, sParam2, Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.GAMEPOINT.sCmd) = 0 then begin
      CmdGamePoint(@g_GameCommand.GAMEPOINT, sParam1, sParam2,
        Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CREDITPOINT.sCmd) = 0 then begin
      CmdCreditPoint(@g_GameCommand.CREDITPOINT, sParam1, sParam2,
        Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.TRAINING.sCmd) = 0 then begin
      CmdTrainingSkill(@g_GameCommand.TRAINING, sParam1, sParam2,
        Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELETEITEM.sCmd) = 0 then begin
      CmdDeleteItem(@g_GameCommand.DELETEITEM, sParam1, sParam2,
        Str_ToInt(sParam3, 1));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELETESKILL.sCmd) = 0 then begin
      CmdDelSkill(@g_GameCommand.DELETESKILL, sParam1, sParam2);
      Exit;
    end;                                                                                            //TrainingSkill
    if CompareText(sCmd, g_GameCommand.TRAININGSKILL.sCmd) = 0 then begin
      CmdTrainingMagic(@g_GameCommand.TRAININGSKILL, sParam1, sParam2,
        Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CLEARMISSION.sCmd) = 0 then begin
      CmdClearMission(@g_GameCommand.CLEARMISSION, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.STARTQUEST.sCmd) = 0 then begin
      CmdStartQuest(@g_GameCommand.STARTQUEST, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DENYIPLOGON.sCmd) = 0 then begin
      CmdDenyIPaddrLogon(@g_GameCommand.DENYIPLOGON, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CHANGEDEARNAME.sCmd) = 0 then begin
      CmdChangeDearName(@g_GameCommand.CHANGEDEARNAME, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ChangeMasterName.sCmd) = 0 then begin
      CmdChangeMasterName(@g_GameCommand.ChangeMasterName, sParam1, sParam2,
        sParam3);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CLEARMON.sCmd) = 0 then begin
      CmdClearMapMonster(@g_GameCommand.CLEARMON, sParam1, sParam2, sParam3,
        sParam4);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DENYACCOUNTLOGON.sCmd) = 0 then begin
      CmdDenyAccountLogon(@g_GameCommand.DENYACCOUNTLOGON, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DENYCHARNAMELOGON.sCmd) = 0 then begin
      CmdDenyCharNameLogon(@g_GameCommand.DENYCHARNAMELOGON, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELDENYIPLOGON.sCmd) = 0 then begin
      CmdDelDenyIPaddrLogon(@g_GameCommand.DELDENYIPLOGON, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELDENYACCOUNTLOGON.sCmd) = 0 then begin
      CmdDelDenyAccountLogon(@g_GameCommand.DELDENYACCOUNTLOGON, sParam1,
        sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DELDENYCHARNAMELOGON.sCmd) = 0 then begin
      CmdDelDenyCharNameLogon(@g_GameCommand.DELDENYCHARNAMELOGON, sParam1,
        sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWDENYIPLOGON.sCmd) = 0 then begin
      CmdShowDenyIPaddrLogon(@g_GameCommand.SHOWDENYIPLOGON, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWDENYACCOUNTLOGON.sCmd) = 0 then begin
      CmdShowDenyAccountLogon(@g_GameCommand.SHOWDENYACCOUNTLOGON, sParam1,
        sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWDENYCHARNAMELOGON.sCmd) = 0 then begin
      CmdShowDenyCharNameLogon(@g_GameCommand.SHOWDENYCHARNAMELOGON, sParam1,
        sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.Mission.sCmd) = 0 then begin
      CmdMission(@g_GameCommand.Mission, sParam1, sParam2);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.MobPlace.sCmd) = 0 then begin
      CmdMobPlace(@g_GameCommand.MobPlace, sParam1, sParam2, sParam3, sParam4);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SetMapMode.sCmd) = 0 then begin
      CmdSetMapMode(g_GameCommand.SetMapMode.sCmd, sParam1, sParam2, sParam3,
        sParam4);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.SHOWMAPMODE.sCmd) = 0 then begin
      CmdShowMapMode(g_GameCommand.SHOWMAPMODE.sCmd, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CLRPASSWORD.sCmd) = 0 then begin
      CmdClearHumanPassword(g_GameCommand.CLRPASSWORD.sCmd,
        g_GameCommand.CLRPASSWORD.nPermissionMin, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.CONTESTPOINT.sCmd) = 0 then begin
      CmdContestPoint(@g_GameCommand.CONTESTPOINT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.STARTCONTEST.sCmd) = 0 then begin
      CmdStartContest(@g_GameCommand.STARTCONTEST, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ENDCONTEST.sCmd) = 0 then begin
      CmdEndContest(@g_GameCommand.ENDCONTEST, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ANNOUNCEMENT.sCmd) = 0 then begin
      CmdAnnouncement(@g_GameCommand.ANNOUNCEMENT, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DISABLESENDMSG.sCmd) = 0 then begin
      CmdDisableSendMsg(@g_GameCommand.DISABLESENDMSG, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.ENABLESENDMSG.sCmd) = 0 then begin
      CmdEnableSendMsg(@g_GameCommand.ENABLESENDMSG, sParam1);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.REFINEWEAPON.sCmd) = 0 then begin
      CmdRefineWeapon(@g_GameCommand.REFINEWEAPON, Str_ToInt(sParam1, 0),
        Str_ToInt(sParam2, 0), Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.DISABLESENDMSGLIST.sCmd) = 0 then begin
      CmdDisableSendMsgList(@g_GameCommand.DISABLESENDMSGLIST);
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.BINDGOLD.sCmd) = 0 then begin
      CmdBindGold(@g_GameCommand.BINDGOLD, sParam1, sParam2, Str_ToInt(sParam3, 0));
      Exit;
    end;
    if CompareText(sCmd, g_GameCommand.BINDGAMEGOLD.sCmd) = 0 then begin
      CmdBindGameGold(@g_GameCommand.BINDGAMEGOLD, sParam1, sParam2, Str_ToInt(sParam3, 0));
      Exit;
    end;
    if m_btPermissionGM > 4 then begin
      if CompareText(sCmd, g_GameCommand.BACKSTEP.sCmd) = 0 then begin
        CmdBackStep(sCmd, Str_ToInt(sParam1, 0), Str_ToInt(sParam2, 1));
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.BALL.sCmd) = 0 then begin                                  //精神波
        Exit;
      end;

      if CompareText(sCmd, g_GameCommand.CHANGELUCK.sCmd) = 0 then begin
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.HUNGER.sCmd) = 0 then begin
        CmdHunger(g_GameCommand.HUNGER.sCmd, sParam1, Str_ToInt(sParam2, 0));
        Exit;
      end;

      if CompareText(sCmd, g_GameCommand.NameColor.sCmd) = 0 then begin
        Exit;
      end;

      if CompareText(sCmd, g_GameCommand.TRANSPARECY.sCmd) = 0 then begin
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.LEVEL0.sCmd) = 0 then begin
        Exit;
      end;

      if CompareText(sCmd, g_GameCommand.SETFLAG.sCmd) = 0 then begin
        PlayObject := UserEngine.GetPlayObject(sParam1);
        if PlayObject <> nil then begin
          nFlag := Str_ToInt(sParam2, 0);
          dwValue := Str_ToInt(sParam3, 0);
          PlayObject.SetQuestFlagStatus(nFlag, dwValue);
          if PlayObject.GetQuestFalgStatus(nFlag) = 1 then begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = ON', c_Green, t_Hint);
          end else begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = OFF', c_Green, t_Hint);
          end;
        end else begin
          SysMsg('@' + g_GameCommand.SETFLAG.sCmd + sHint11, c_Red, t_Hint);
        end;
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.SETOPEN.sCmd) = 0 then begin
        PlayObject := UserEngine.GetPlayObject(sParam1);
        if PlayObject <> nil then begin
          nFlag := Str_ToInt(sParam2, 0);
          dwValue := Str_ToInt(sParam3, 0);
          PlayObject.SetQuestUnitOpenStatus(nFlag, dwValue);
          if PlayObject.GetQuestUnitOpenStatus(nFlag) = 1 then begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = ON', c_Green, t_Hint);
          end else begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = OFF', c_Green, t_Hint);
          end;
        end else begin
          SysMsg('@' + g_GameCommand.SETOPEN.sCmd + sHint11, c_Red, t_Hint);
        end;
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.SETUNIT.sCmd) = 0 then begin
        PlayObject := UserEngine.GetPlayObject(sParam1);
        if PlayObject <> nil then begin
          nFlag := Str_ToInt(sParam2, 0);
          dwValue := Str_ToInt(sParam3, 0);
          PlayObject.SetQuestUnitStatus(nFlag, dwValue);
          if PlayObject.GetQuestUnitStatus(nFlag) = 1 then begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = ON', c_Green, t_Hint);
          end else begin
            SysMsg(PlayObject.m_sCharName + ': [' + IntToStr(nFlag) + '] = OFF', c_Green, t_Hint);
          end;
        end else begin
          SysMsg('@' + g_GameCommand.SETUNIT.sCmd + sHint11, c_Red, t_Hint);
        end;
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.RECONNECTION.sCmd) = 0 then begin
        CmdReconnection(sCmd, sParam1, sParam2);
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.DISABLEFILTER.sCmd) = 0 then begin
        CmdDisableFilter(sCmd, sParam1);
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.CHGUSERFULL.sCmd) = 0 then begin
        CmdChangeUserFull(sCmd, sParam1);
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.CHGZENFASTSTEP.sCmd) = 0 then begin
        CmdChangeZenFastStep(sCmd, sParam1);
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.OXQUIZROOM.sCmd) = 0 then begin
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.GSA.sCmd) = 0 then begin
        Exit;
      end;
      if CompareText(sCmd, g_GameCommand.CHANGEITEMNAME.sCmd) = 0 then begin
        CmdChangeItemName(g_GameCommand.CHANGEITEMNAME.sCmd, sParam1, sParam2, sParam3);
        Exit;
      end;

      if (m_btPermissionGM >= 5) or (g_Config.boTestServer) then begin
        if CompareText(sCmd, g_GameCommand.FIREBURN.sCmd) = 0 then begin
          CmdFireBurn(Str_ToInt(sParam1, 0), Str_ToInt(sParam2, 0), Str_ToInt(sParam3, 0));
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.TESTFIRE.sCmd) = 0 then begin
          CmdTestFire(sCmd, Str_ToInt(sParam1, 0), Str_ToInt(sParam2, 0),
            Str_ToInt(sParam3, 0), Str_ToInt(sParam4, 0));
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.TESTSTATUS.sCmd) = 0 then begin
          CmdTestStatus(sCmd, Str_ToInt(sParam1, -1), Str_ToInt(sParam2, 0));
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.TESTGOLDCHANGE.sCmd) = 0 then begin
          Exit;
        end;

        if CompareText(sCmd, g_GameCommand.RELOADADMIN.sCmd) = 0 then begin
          CmdReLoadAdmin(g_GameCommand.RELOADADMIN.sCmd);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ReLoadNpc.sCmd) = 0 then begin
          CmdReloadNpc(sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADMANAGE.sCmd) = 0 then begin
          CmdReloadManage(@g_GameCommand.RELOADMANAGE, sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADROBOTMANAGE.sCmd) = 0 then begin
          CmdReloadRobotManage();
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADROBOT.sCmd) = 0 then begin
          CmdReloadRobot();
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADMONITEMS.sCmd) = 0 then begin
          CmdReloadMonItems();
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADDIARY.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADITEMDB.sCmd) = 0 then begin
          FrmDB.LoadItemsDB();
          SysMsg(sHint12, c_Green, t_Hint);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADMAGICDB.sCmd) = 0 then begin
          FrmDB.LoadMagicDB();
          SysMsg('魔法数据库重新加载完成。', c_Green, t_Hint);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADMONSTERDB.sCmd) = 0 then begin
          FrmDB.LoadMonsterDB();
          SysMsg(sHint13, c_Green, t_Hint);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADMINMAP.sCmd) = 0 then begin
          FrmDB.LoadMinMap();
          g_MapManager.ReSetMinMap();
          SysMsg(sHint14, c_Green, t_Hint);
          Exit;
        end;

        if CompareText(sCmd, g_GameCommand.ADJUESTLEVEL.sCmd) = 0 then begin
          CmdAdjuestLevel(@g_GameCommand.ADJUESTLEVEL, sParam1,
            Str_ToInt(sParam2, 1));
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ADJUESTEXP.sCmd) = 0 then begin
          CmdAdjuestExp(@g_GameCommand.ADJUESTEXP, sParam1, sParam2);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.AddGuild.sCmd) = 0 then begin
          CmdAddGuild(@g_GameCommand.AddGuild, sParam1, sParam2);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.DelGuild.sCmd) = 0 then begin
          CmdDelGuild(@g_GameCommand.DelGuild, sParam1);
          Exit;
        end;
        if (CompareText(sCmd, g_GameCommand.CHANGESABUKLORD.sCmd) = 0) then begin
          CmdChangeSabukLord(@g_GameCommand.CHANGESABUKLORD, sParam1, sParam2,
            True);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.FORCEDWALLCONQUESTWAR.sCmd) = 0 then begin
          CmdForcedWallconquestWar(@g_GameCommand.FORCEDWALLCONQUESTWAR, sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ADDTOITEMEVENT.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ADDTOITEMEVENTASPIECES.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ItemEventList.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.STARTINGGIFTNO.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.DELETEALLITEMEVENT.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.STARTITEMEVENT.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ITEMEVENTTERM.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.ADJUESTTESTLEVEL.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.OPDELETESKILL.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.CHANGEWEAPONDURA.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.RELOADGUILDALL.sCmd) = 0 then begin
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.SPIRIT.sCmd) = 0 then begin
          CmdSpirtStart(g_GameCommand.SPIRIT.sCmd, sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.SPIRITSTOP.sCmd) = 0 then begin
          CmdSpirtStop(g_GameCommand.SPIRITSTOP.sCmd, sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.TESTGETBAGITEM.sCmd) = 0 then begin
          CmdTestGetBagItems(@g_GameCommand.TESTGETBAGITEM, sParam1);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.MOBFIREBURN.sCmd) = 0 then begin
          CmdMobFireBurn(@g_GameCommand.MOBFIREBURN, sParam1, sParam2, sParam3, sParam4, sParam5, sParam6);
          Exit;
        end;
        if CompareText(sCmd, g_GameCommand.TESTSPEEDMODE.sCmd) = 0 then begin
          CmdTestSpeedMode(@g_GameCommand.TESTSPEEDMODE, Str_ToInt(sParam1, 0), Str_ToInt(sParam2, 0));
          Exit;
        end;
      end;
    end;                                                                                            //004D52B5
    SysMsg('@' + sCmd + sHint15, c_Red, t_Hint);
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [sData]));
      MainOutMessage(E.Message);
    end;
  end;
end;

//刷新人物附加属性

procedure TPlayObject.QuerySubAbility;
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnQuerySubAbility(Self);
  except
    MainOutMessage(Format('TPlayObject::OnQuerySubAbility SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

function TPlayObject.QuestCheckItem(sItemName: string; var nCount,
  nParam: Integer; var nDura: Integer): pTUserItem;
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  Result := nil;
  nParam := 0;
  nDura := 0;
  nCount := 0;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (StdItem <> nil) then begin
      if CompareText(StdItem.Name, sItemName) = 0 then begin
        if UserItem.Dura > nDura then begin
          nDura := UserItem.Dura;
          Result := UserItem;
        end;
        Inc(nParam, UserItem.Dura);
        if Result = nil then
          Result := UserItem;
        if CheckSPCode(StdItem.Reserved, RE_ALLOWPILE) then
          Inc(nCount, UserItem.Dura)
        else
          Inc(nCount);
      end;
    end;
  end;
end;

function TPlayObject.QuestCheckItemEx(sItemName: string; nDura: Integer; boParam: Boolean):
  Integer;
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  s1C                                   : string;
begin
  Result := 0;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    s1C := UserEngine.GetStdItemName(UserItem.wIndex);
    if CompareText(s1C, sItemName) = 0 then begin
      if (UserItem.Dura >= nDura) and (boParam = False) then begin
        Inc(Result);
      end;
      if (UserItem.Dura = nDura) and (boParam = True) then begin
        Inc(Result);
      end;
    end;
  end;
end;

function TPlayObject.QuestCheckItemX(sItemName: string; var nCount,
  nParam: Integer; var nDura: Integer): pTUserItem;                                                 //004C4B78
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  s1C                                   : string;
begin
  Result := nil;
  if m_nStoreMakeIndex = 0 then Exit;
  nParam := 0;
  nDura := 0;
  nCount := 0;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if UserItem.MakeIndex = m_nStoreMakeIndex then begin
      if UserItem.Dura > nDura then begin
        nDura := UserItem.Dura;
        Result := UserItem;
        Inc(nCount);
        Break;
      end;
    end;
  end;
end;

function TPlayObject.QuestTakeCheckItem(CheckItem: pTUserItem): Boolean;
//004C4F6C
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  Result := False;
  for i := m_ItemList.Count - 1 downto 0 do begin
    UserItem := m_ItemList.Items[i];
    if UserItem = CheckItem then begin
      SendDelItems(UserItem);
      Dispose(UserItem);
      m_ItemList.Delete(i);
      Result := True;
      Break;
    end;
  end;
  for i := Low(m_UseItems) to High(m_UseItems) do begin
    if @m_UseItems[i] = CheckItem then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
      if StdItem = nil then Continue;
      SendDelItems(@m_UseItems[i]);
      m_UseItems[i].wIndex := 0;
      //取下装备触发脚本
      m_sScriptParam[0] := StdItem.Name;
      m_sScriptParam[1] := StdItem.FilterName;
      ExecuteScript(g_FunctionNPC, '@TakeOff' + IntToStr(i));
      Result := True;
      Break;
    end;
  end;
end;

procedure TPlayObject.ReadAllBook();
var
  i                                     : Integer;
  Magic                                 : pTMagic;
begin
  for i := 0 to UserEngine.m_MagicList.Count - 1 do begin
    Magic := UserEngine.m_MagicList.Items[i];
    AddItemSkill(Magic, 2, 0, 100000);
  end;
end;

procedure TPlayObject.RecalcAbilitys(boAction: Boolean = False);
begin
      FillChar(m_ExemptHurt, SizeOf(m_ExemptHurt), 0);
  inherited RecalcAbilitys(boAction);
  m_nAllIncReply := 0;

  RecalcAdjusBonus();
  RecalcAdditionalAbil();                                                                           //元婴附加属性

  SendUpdateMsg(Self, RM_CHARSTATUSCHANGED, m_nHitSpeed, m_nCharStatus, 0, 0, GetCharStatusMsg);
end;

procedure TPlayObject.RecalcAbilitysEx();
begin
  inherited;
  RecalcAddProvisionalAbil();                                                                       //脚本增加的人物临时属性
  RecalcAddInosculatePneumaAbil();                                                                  //融合元神附加属性
  RecalcMentalLevelAbilitys;                                                                        //天元心法附加属性
  RecalcAddPetAbil;                                                                                 //灵兽附加属性
end;

//元婴附加属性

procedure TPlayObject.RecalcAdditionalAbil();
begin
  if not m_boPneuma then begin
    m_WAbil.DC := MakeLong(loword(m_WAbil.DC) + (m_Dan.SoulBaby.Abil.btDc shr 4), hiword(m_WAbil.DC) + (m_Dan.SoulBaby.Abil.btDc and $0F));
    m_WAbil.MC := MakeLong(loword(m_WAbil.MC) + (m_Dan.SoulBaby.Abil.btMc shr 4), hiword(m_WAbil.MC) + (m_Dan.SoulBaby.Abil.btMc and $0F));
    m_WAbil.SC := MakeLong(loword(m_WAbil.SC) + (m_Dan.SoulBaby.Abil.btSc shr 4), hiword(m_WAbil.SC) + (m_Dan.SoulBaby.Abil.btSc and $0F));
    m_WAbil.AC := MakeLong(loword(m_WAbil.AC) + (m_Dan.SoulBaby.Abil.btAC shr 4), hiword(m_WAbil.AC) + (m_Dan.SoulBaby.Abil.btAC and $0F));
    m_WAbil.MAC := MakeLong(loword(m_WAbil.MAC) + (m_Dan.SoulBaby.Abil.btMAC shr 4), hiword(m_WAbil.MAC) + (m_Dan.SoulBaby.Abil.btMAC and $0F));
    if (m_PneumaObject <> nil) then begin
      TPlayObject(m_PneumaObject).RecalcAbilitys;
      m_PneumaObject.SendMsg(m_PneumaObject, RM_ABILITY, 0, 0, 0, 0, '');
    end;
  end else begin
    if (m_PneumaObject <> nil) then begin
      m_WAbil.dwMaxHP := _MIN(MAXHUMHP, m_WAbil.dwMaxHP + TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btHP);
      m_WAbil.DC := MakeLong(loword(m_WAbil.DC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma shr 4),
        hiword(m_WAbil.DC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma and $0F));
      m_WAbil.MC := MakeLong(loword(m_WAbil.MC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma shr 4),
        hiword(m_WAbil.MC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma and $0F));
      m_WAbil.SC := MakeLong(loword(m_WAbil.SC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma shr 4),
        hiword(m_WAbil.SC) + (TPlayObject(m_PneumaObject).m_Dan.SoulBaby.Abil.btPneuma and $0F));
    end;
  end;
end;

//重新计算校正点数

procedure TPlayObject.RecalcAdjusBonus();

  procedure AdjustAb(Abil: word; Val: word; var lov, hiv: word);
  var
    Lo, Hi                              : byte;
    i                                   : Integer;
  begin
    Lo := LoByte(Abil);
    Hi := HiByte(Abil);
    lov := 0;
    hiv := 0;
    for i := 1 to Val do begin
      if Lo + 1 < Hi then begin
        Inc(Lo);
        Inc(lov);
      end else begin
        Inc(Hi);
        Inc(hiv);
      end;
    end;
  end;
var
  BonusTick                             : pTNakedAbility;
  NakedAbil                             : pTNakedAbility;
  adc, amc, asc, aac, amac              : Integer;
  ldc, lmc, lsc, lac, lmac, hdc, hmc, hsc, hac, hmac: word;
begin
  BonusTick := nil;
  NakedAbil := nil;
  case m_btJob of
    0: begin
        BonusTick := @g_Config.BonusAbilofWarr;
        NakedAbil := @g_Config.NakedAbilofWarr;
      end;
    1: begin
        BonusTick := @g_Config.BonusAbilofWizard;
        NakedAbil := @g_Config.NakedAbilofWizard;
      end;
    2: begin
        BonusTick := @g_Config.BonusAbilofTaos;
        NakedAbil := @g_Config.NakedAbilofTaos;
      end;
    3: begin
        BonusTick := @g_Config.BonusAbilofGoblin;
        NakedAbil := @g_Config.NakedAbilofGoblin;
      end;
  end;

  adc := m_BonusAbil.DC div BonusTick.DC;
  amc := m_BonusAbil.MC div BonusTick.MC;
  asc := m_BonusAbil.SC div BonusTick.SC;
  aac := m_BonusAbil.AC div BonusTick.AC;
  amac := m_BonusAbil.MAC div BonusTick.MAC;

  AdjustAb(NakedAbil.DC, adc, ldc, hdc);
  AdjustAb(NakedAbil.MC, amc, lmc, hmc);
  AdjustAb(NakedAbil.SC, asc, lsc, hsc);
  AdjustAb(NakedAbil.AC, aac, lac, hac);
  AdjustAb(NakedAbil.MAC, amac, lmac, hmac);

  if (m_btJob = 3) then
    m_WAbil.GC := MakeLong(loword(m_WAbil.GC) + ldc, hiword(m_WAbil.GC) + hdc)
  else
    m_WAbil.DC := MakeLong(loword(m_WAbil.DC) + ldc, hiword(m_WAbil.DC) + hdc);

  m_WAbil.MC := MakeLong(loword(m_WAbil.MC) + lmc, hiword(m_WAbil.MC) + hmc);
  m_WAbil.SC := MakeLong(loword(m_WAbil.SC) + lsc, hiword(m_WAbil.SC) + hsc);
  m_WAbil.AC := MakeLong(loword(m_WAbil.AC) + lac, hiword(m_WAbil.AC) + hac);
  m_WAbil.MAC := MakeLong(loword(m_WAbil.MAC) + lmac, hiword(m_WAbil.MAC) + hmac);

  m_WAbil.dwMaxHP := _MIN(MAXHUMHP, m_WAbil.dwMaxHP + m_BonusAbil.HP div BonusTick.HP);
  m_WAbil.dwMaxMP := _MIN(MAXHUMMP, m_WAbil.dwMaxMP + m_BonusAbil.MP div BonusTick.MP);
  m_dwSpeedPoint := m_dwSpeedPoint + m_BonusAbil.Speed div BonusTick.Speed;
  m_dwHitPoint := m_dwHitPoint + m_BonusAbil.Hit div BonusTick.Hit;
end;

procedure TPlayObject.RecalcTigerLevelAbilitys;
var
  TigerAbility                          : pTAbilityOfTiger;
begin
  if m_boPneuma then Exit;
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王

  if (m_TorDDM.Tiger.DB.level >= 0) then begin
    TigerAbility := UserEngine.GetTigerAbilByLevel(m_TorDDM.Tiger.DB.level, m_TorDDM.Tiger.DB.Dragon);
    if TigerAbility <> nil then begin
      //读取的数据库属性
      m_TorDDM.Tiger.Abil.MaxExp := TigerAbility.MaxExp;
      m_TorDDM.Tiger.Abil.MaxHP := TigerAbility.MaxHP;
      m_TorDDM.Tiger.AddAbil.HP := TigerAbility.MaxHP;
      m_TorDDM.Tiger.Abil.DC := TigerAbility.DC;
      m_TorDDM.Tiger.Abil.DC2 := TigerAbility.DC2;
      m_TorDDM.Tiger.Abil.MC := TigerAbility.MC;
      m_TorDDM.Tiger.Abil.MC2 := TigerAbility.MC2;
      m_TorDDM.Tiger.Abil.AC := TigerAbility.AC;
      m_TorDDM.Tiger.Abil.AC2 := TigerAbility.AC2;
      m_TorDDM.Tiger.Abil.MAC := TigerAbility.MAC;
      m_TorDDM.Tiger.Abil.MAC2 := TigerAbility.MAC2;

      m_TorDDM.Tiger.Abil.HitPoint := TigerAbility.HitPoint;
      m_TorDDM.Tiger.Abil.MagicNicety := TigerAbility.MagicNicety;
      m_TorDDM.Tiger.Abil.SpeedPoint := TigerAbility.SpeedPoint;
      m_TorDDM.Tiger.Abil.AntiMagic := TigerAbility.AntiMagic;
      m_TorDDM.Tiger.Abil.Felement := TigerAbility.Felement;
    end;
  end;
end;

procedure TPlayObject.RecalcTigerAbility;
var
  i                                     : Integer;
  StdItem                               : pTStdItem;
  TigerAbility                          : pTAbilityOfTiger;
  boWeared                              : Boolean;
  procedure GetItemAccessory(Item: TUserItem; var AddAbility: TAddAbilityOfTiger);
  var
    StdItem                             : pTStdItem;
    StdItemA                            : TStdItem;
    i                                   : Integer;
  begin
    StdItem := UserEngine.GetStdItem(Item.wIndex);
    if StdItem = nil then Exit;
    StdItemA := StdItem^;
    ItemUnit.GetItemAddValue(@Item, StdItemA);
    AddAbility.AC := MakeLong(_MIN(High(word), LoWord(AddAbility.AC) + LoWord(StdItemA.AC)), _MIN(High(word), HiWord(AddAbility.AC) + HiWord(StdItemA.AC)));
    AddAbility.MAC := MakeLong(_MIN(High(word), LoWord(AddAbility.MAC) + LoWord(StdItemA.MAC)), _MIN(High(word), HiWord(AddAbility.MAC) + HiWord(StdItemA.MAC)));
    AddAbility.DC := MakeLong(_MIN(High(word), LoWord(AddAbility.DC) + LoWord(StdItemA.DC)), _MIN(High(word), HiWord(AddAbility.DC) + HiWord(StdItemA.DC)));
    AddAbility.MC := MakeLong(_MIN(High(word), LoWord(AddAbility.MC) + LoWord(StdItemA.MC)), _MIN(High(word), HiWord(AddAbility.MC) + HiWord(StdItemA.MC)));

    AddAbility.HitPoint := _MIN(High(byte), AddAbility.HitPoint + LoWord(StdItemA.MC));
    AddAbility.SpeedPoint := _MIN(High(byte), AddAbility.SpeedPoint + HiWord(StdItemA.MC));
    AddAbility.AntiMagic := _MIN(High(byte), AddAbility.AntiMagic + LoWord(StdItemA.SC));
    AddAbility.FelementDC := _MIN(High(word), AddAbility.FelementDC + HiWord(StdItemA.SC));
    AddAbility.FelementAC := _MIN(High(word), AddAbility.FelementAC + HiWord(StdItemA.SC));
    AddAbility.HP := _MIN(MAXHUMHP, AddAbility.HP + StdItemA.NeedAmbit);
  end;
begin
  if m_boPneuma then Exit;
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王
  FillChar(m_TorDDM.Tiger.AddAbil, SizeOf(TAddAbilityOfTiger), #0);

  //计算基本属性
  m_TorDDM.Tiger.AddAbil.AC := MakeLong(m_TorDDM.Tiger.Abil.AC, m_TorDDM.Tiger.Abil.AC2);
  m_TorDDM.Tiger.AddAbil.MAC := MakeLong(m_TorDDM.Tiger.Abil.MAC, m_TorDDM.Tiger.Abil.MAC2);
  m_TorDDM.Tiger.AddAbil.DC := MakeLong(m_TorDDM.Tiger.Abil.DC, m_TorDDM.Tiger.Abil.DC2);
  m_TorDDM.Tiger.AddAbil.MC := MakeLong(m_TorDDM.Tiger.Abil.MC, m_TorDDM.Tiger.Abil.MC2);
  m_TorDDM.Tiger.AddAbil.HitPoint := m_TorDDM.Tiger.Abil.HitPoint;
  m_TorDDM.Tiger.AddAbil.MagicNicety := m_TorDDM.Tiger.Abil.MagicNicety;
  m_TorDDM.Tiger.AddAbil.SpeedPoint := m_TorDDM.Tiger.Abil.SpeedPoint;
  m_TorDDM.Tiger.AddAbil.AntiMagic := m_TorDDM.Tiger.Abil.AntiMagic;
  m_TorDDM.Tiger.AddAbil.HP := _MIN(MAXHUMHP, m_TorDDM.Tiger.Abil.MaxHP + m_TorDDM.Tiger.ProAbil.HP);
  m_TorDDM.Tiger.AddAbil.FelementDC := _MIN(High(word), m_TorDDM.Tiger.Abil.Felement + m_TorDDM.Tiger.ProAbil.Felement);
  m_TorDDM.Tiger.AddAbil.FelementAC := _MIN(High(word), m_TorDDM.Tiger.Abil.Felement + m_TorDDM.Tiger.ProAbil.Felement);

  //计算虎王装备属性
  boWeared := True;
  for i := 0 to MAX_TIGER_ITEM_COUNT - 1 do begin
    if (m_TorDDM.Tiger.Items[i].wIndex <= 0) or (m_TorDDM.Tiger.Items[i].Dura <= 0) then begin
      boWeared := False;
      Continue;
    end;
    //物品不存在或物品已损坏
    StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[i].wIndex);
    if StdItem = nil then Continue;
    GetItemAccessory(m_TorDDM.Tiger.Items[i], m_TorDDM.Tiger.AddAbil);
  end;
  SendMsg(Self, RM_TIGERADDABIL, 0, 0, 0, 0, '');

  if (m_Tiger <> nil) then begin
    SendTigerInfo;
    m_Tiger.RecalcAbilitys;
    if m_TorDDM.Tiger.DB.Dragon = 0 then begin
      if (m_TorDDM.Tiger.DB.level >= 50) then begin
        m_Tiger.m_wAppr := 349;
        m_Tiger.m_sCharName := '啸天虎王';
      end else begin
        m_Tiger.m_wAppr := 350;
        m_Tiger.m_sCharName := '啸天虎';
      end;
      if boWeared then m_Tiger.m_wAppr := 384;
      m_Tiger.RefShowName;
      m_Tiger.FeatureChanged;
    end;
  end;
end;

//根据通灵塔等级和官职获得属性点加成

procedure TPlayObject.RecalcTowerAbility();
var
  i, nTowerGrade, nRank                 : Integer;
  nMinValue, nMaxValue                  : Integer;
  btPrOffer                             : byte;
begin
  btPrOffer := m_GuildTowerInfo.btPrOffer;
  FillChar(m_GuildTowerInfo, SizeOf(TGuildTowerInfo), #0);
  if m_MyGuild = nil then Exit;
  nTowerGrade := _MIN(10, TGuild(m_MyGuild).btTowerGrade);
  nRank := _MIN(11, m_nGuildRankNo);

  if (nTowerGrade > 0) then begin
    m_GuildTowerInfo.wX := TGuild(m_MyGuild).wTowerX;
    m_GuildTowerInfo.wY := TGuild(m_MyGuild).wTowerY;
    m_GuildTowerInfo.btResFull := byte(TGuild(m_MyGuild).boTowerStatus);
    m_GuildTowerInfo.btPrOffer := btPrOffer;
    //以下为本体DC\MC\SC计算公式
    case m_btJob of
      0: begin
          nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wDC) > 0) * (LoByte(g_Config.GuildTowerAbility.wDC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wDC) > 0) * (HiByte(g_Config.GuildTowerAbility.wDC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          m_GuildTowerInfo.Ability.wDC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));
        end;
      1: begin
          nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wMC) > 0) * (LoByte(g_Config.GuildTowerAbility.wMC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wMC) > 0) * (HiByte(g_Config.GuildTowerAbility.wMC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          m_GuildTowerInfo.Ability.wMC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));
        end;
      2: begin
          nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wSC) > 0) * (LoByte(g_Config.GuildTowerAbility.wSC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wSC) > 0) * (HiByte(g_Config.GuildTowerAbility.wSC) - ((nRank + 7) div 9) + nTowerGrade - 1);
          m_GuildTowerInfo.Ability.wSC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));
        end;
      3: begin                                                                                      //妖

        end;

    end;
    //以下为计算AC、MAC公式
    if nRank < 3 then begin
      nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wAC) > 0) * (nTowerGrade + LoByte(g_Config.GuildTowerAbility.wAC) - m_nGuildRankNo);
      nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wAC) > 0) * (nTowerGrade + HiByte(g_Config.GuildTowerAbility.wAC) - m_nGuildRankNo);
      m_GuildTowerInfo.Ability.wAC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));

      nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wMAC) > 0) * (nTowerGrade + LoByte(g_Config.GuildTowerAbility.wMAC) - m_nGuildRankNo);
      nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wMAC) > 0) * (nTowerGrade + HiByte(g_Config.GuildTowerAbility.wMAC) - m_nGuildRankNo);
      m_GuildTowerInfo.Ability.wMAC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));
    end else begin
      nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wAC) > 0) * (nTowerGrade + LoByte(g_Config.GuildTowerAbility.wAC) - ((nRank + 3) div 2));
      nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wAC) > 0) * (nTowerGrade + HiByte(g_Config.GuildTowerAbility.wAC) - ((nRank + 3) div 2));
      m_GuildTowerInfo.Ability.wAC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));

      nMinValue := byte(LoByte(g_Config.GuildTowerAbility.wMAC) > 0) * (nTowerGrade + LoByte(g_Config.GuildTowerAbility.wMAC) - ((nRank + 3) div 2));
      nMaxValue := byte(HiByte(g_Config.GuildTowerAbility.wMAC) > 0) * (nTowerGrade + HiByte(g_Config.GuildTowerAbility.wMAC) - ((nRank + 3) div 2));
      m_GuildTowerInfo.Ability.wMAC := MakeWord(_MIN(High(byte), nMinValue * g_Config.nGuildTowerAbilityRate div 10), _MIN(High(byte), nMaxValue * g_Config.nGuildTowerAbilityRate div 10));
    end;
    //以下为命中、魔法躲避等属性计算
    if nTowerGrade >= 5 then begin
      m_GuildTowerInfo.Ability.btMagicNicety := byte(g_Config.GuildTowerAbility.btMagicNicety > 0) * (nTowerGrade + g_Config.GuildTowerAbility.btMagicNicety - 5);
      m_GuildTowerInfo.Ability.btHitPoint := byte(g_Config.GuildTowerAbility.btHitPoint > 0) * (nTowerGrade + g_Config.GuildTowerAbility.btHitPoint - 5);
      m_GuildTowerInfo.Ability.btAntiMagic := byte(g_Config.GuildTowerAbility.btAntiMagic > 0) * (nTowerGrade + g_Config.GuildTowerAbility.btAntiMagic - 5);
      m_GuildTowerInfo.Ability.btSpeedPoint := byte(g_Config.GuildTowerAbility.btSpeedPoint > 0) * (nTowerGrade + g_Config.GuildTowerAbility.btSpeedPoint - 5);
    end;
    //元神属性与本体一样
    Move(m_GuildTowerInfo.Ability, m_GuildTowerInfo.u_Ability, SizeOf(TGuildTowerAbility));
  end;
end;

function TPlayObject.RecallHuman(sHumName: string; wRecallType: word): Boolean;
var
  PlayObject                            : TPlayObject;
  nX, nY, n18, n1C, nMapIndex           : Integer;
begin
  Result := False;
  PlayObject := UserEngine.GetPlayObject(sHumName);
  if PlayObject <> nil then begin
    if PlayObject.m_wShopItemCount > 0 then begin
      SysMsg('对方在摆摊,无法被召唤。', c_Red, t_Hint);
      PlayObject.SysMsg(m_sCharName + ' 正在召唤你,只有结束摆摊才能被召唤。', c_Red, t_Hint);
      Exit;
    end;
    if PlayObject.m_boArrow then begin
      SysMsg('对方正在执行任务,无法被召唤。', c_Red, t_Hint);
      PlayObject.SysMsg(m_sCharName + ' 正在召唤你,只有结束当前任务才能被召唤。', c_Red, t_Hint);
      Exit;
    end;

    if GetFrontPosition(nX, nY) then begin
      if GetCanMovePosition(nX, nY, 3, n18, n1C) then begin
        PlayObject.SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
        nMapIndex := m_PEnvir.Index;
        PlayObject.SpaceMove(m_sMapName, n18, n1C, 0, @nMapIndex);
        if wRecallType <> 0 then
          PlayObject.SendRefMsg(RM_510, 1, 0, wRecallType, 0, '');
      end;
      Result := True;
    end else begin
      SysMsg('召唤失败!!!', c_Red, t_Hint);
    end;
  end else begin
    SysMsg(Format(g_sNowNotOnLineOrOnOtherServer, [sHumName]), c_Red, t_Hint);
  end;
end;

procedure TPlayObject.RecordHomeXY(nParam1: Integer; nMapIdx: Integer);
begin
  if (nParam1 < 0) or (nMapIdx < 0) then Exit;

  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnRecordHomeXY(Self, nParam1, nMapIdx);
  except
    MainOutMessage(Format('TPlayObject::RecordHomeXY SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

procedure TPlayObject.RecordHomeXY(nParam1: Integer; sMsg: string);
var
  sMapName                              : string;
begin
  if (sMsg <> '') then begin
    sMapName := DeCodeString(sMsg);
    if g_Config.boClassicServer then begin
      if (sMapName = '0') then
        RecordHomeXY(nParam1, 2)
      else if (sMapName = '2') then
        RecordHomeXY(nParam1, 3)
      else if (sMapName = '7') then
        RecordHomeXY(nParam1, 6)
      else if (sMapName = '5') then
        RecordHomeXY(nParam1, 5)
      else if (sMapName = '4') then
        RecordHomeXY(nParam1, 4)
      else if (sMapName = 'haidi') then
        RecordHomeXY(nParam1, 9)
      else if (sMapName = '1') then
        RecordHomeXY(nParam1, 1)
      else if (sMapName = 'zqd') then
        RecordHomeXY(nParam1, 0);
    end else begin
      if (sMapName = '0') then
        RecordHomeXY(nParam1, 1)
      else if (sMapName = '1') then
        RecordHomeXY(nParam1, 0)
      else if (sMapName = '2') then
        RecordHomeXY(nParam1, 2)
      else if (sMapName = '4') then
        RecordHomeXY(nParam1, 3)
      else if (sMapName = '5') then
        RecordHomeXY(nParam1, 4)
      else if (sMapName = '7') then
        RecordHomeXY(nParam1, 5)
    end;
  end;
end;

//我的状态

procedure TPlayObject.RefMyStatus();
begin
  RecalcAbilitys();
  SendMsg(Self, RM_MYSTATUS, 0, 0, 0, 0, '');
end;

procedure TPlayObject.RefRankInfo(nRankNo: Integer; sRankName: string);
begin
  m_nGuildRankNo := nRankNo;
  m_sGuildRankName := sRankName;
  SendMsg(Self, RM_CHANGEGUILDNAME, 0, 0, 0, 0, '');
end;

//地区状态(只发送给自己)

procedure TPlayObject.RefUserState();                                                               //004D6870
var
  N8                                    : Integer;
begin
  N8 := 0;
  if m_PEnvir.m_MapFlag.boFight then N8 := N8 or 1;
  if m_PEnvir.m_MapFlag.boSAFE then N8 := N8 or 2;
  if m_boInFreePKArea then N8 := N8 or 4;
  SendDefMessage(SM_AREASTATE, N8, 0, 0, 0, '');
end;

{释放附魔属性}

procedure TPlayObject.ReleaseEvil(nMakeIndex: Integer);
var
  UserItem                              : pTUserItem;
  pStdItem                              : pTStdItem;
begin
  GetUserItemByMakeIndex(nMakeIndex, UserItem);
  if (UserItem <> nil) then begin
    pStdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (pStdItem <> nil) then begin
      if (UserItem.Evil.sName = '') or (UserItem.Evil.MakeIndex = 0) then begin
        SysMsg(Format('没有从%s中感应到心魔气息。', [pStdItem.FilterName]), c_Red, t_Hint);
        Exit;
      end;
      FillChar(UserItem.Evil, SizeOf(TEvil), #0);                                                   //删除心魔数据
      SendUpdateItem(UserItem, false);
      SendDefMessage(SM_ITEMEVIL, Integer(Self), LoWord(nMakeIndex), HiWord(nMakeIndex), 0, '');
      SendRefMsg(RM_510, 1, 0, 60, 0, '');
    end;
  end;
end;

function TPlayObject.RepairWeapon: Boolean;
var
  nDura                                 : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  Result := False;
  UserItem := @m_UseItems[U_WEAPON];
  if (UserItem.wIndex <= 0) or (UserItem.DuraMax <= UserItem.Dura) then Exit;
  StdItem := UserEngine.GetStdItem(UserItem.wIndex);
  if StdItem = nil then Exit;
  {物品控制-禁止修理}
  if CheckSPCode(StdItem.SPCode, SP_DISABLEREPAIR) then begin
    SysMsg('此物品禁止修理', c_Red, t_Hint);
    Exit;
  end;
  Dec(UserItem.DuraMax, (UserItem.DuraMax - UserItem.Dura) div
    g_Config.nRepairItemDecDura {30});
  nDura := _MIN(5000, UserItem.DuraMax - UserItem.Dura);
  if nDura > 0 then begin
    Inc(UserItem.Dura, nDura);
    SendMsg(Self, RM_DURACHANGE, 1, UserItem.Dura, UserItem.DuraMax, 0, '');
    SysMsg(g_sWeaponRepairSuccess {'武器修复成功...'}, c_Green, t_Hint);
    Result := True;
  end;
end;

procedure TPlayObject.ReQuestGuildWar(sGuildName: string; WarTime: Integer = 0);
var
  Guild                                 : TGuild;
  WarGuild                              : pTWarGuild;
  boReQuestOK                           : Boolean;
begin
  if not IsGuildMaster then begin
    SysMsg('只有行会掌门人才能申请!!!', c_Red, t_Hint);
    Exit;
  end;
  if g_Config.nServerNumber <> 0 then begin
    SysMsg('这个命令不能在本服务器上使用!!!', c_Red,
      t_Hint);
    Exit;
  end;
  Guild := g_GuildManager.FindGuild(sGuildName);
  if Guild = nil then begin
    SysMsg('行会不存在!!!', c_Red, t_Hint);
    Exit;
  end;
  boReQuestOK := False;
  WarGuild := TGuild(m_MyGuild).AddWarGuild(Guild);
  if WarGuild <> nil then begin
    if Guild.AddWarGuild(TGuild(m_MyGuild)) = nil then begin
      WarGuild.dwWarTick := 0;
    end else begin
      boReQuestOK := True;
    end;
  end;
  if boReQuestOK then begin
    UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber,
      TGuild(m_MyGuild).sGuildName);
    UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, Guild.sGuildName);
  end;

end;

procedure TPlayObject.ClientCheckVerifyCode(sVerifyCode: string; boOutTime: Boolean = False);
var
  NPC                                   : TNormNpc;
  boNo                                  : Boolean;
begin
  if m_VerifyCodeInfo.pNextNpc <> nil then begin
    try
      NPC := UserEngine.FindMerchant(m_VerifyCodeInfo.pNextNpc);
      if NPC = nil then NPC := UserEngine.FindNPC(m_VerifyCodeInfo.pNextNpc);
    finally
      m_VerifyCodeInfo.pNextNpc := nil;
      m_VerifyCodeInfo.nBeginTick := GetTickCount();
    end;
    if NPC <> nil then begin
      if m_VerifyCodeInfo.sNextLabel <> '' then begin
        try
          if sVerifyCode <> '' then
            sVerifyCode := UpperCase(DeCodeString(sVerifyCode));
          boNo := sVerifyCode <> m_VerifyCodeInfo.sVerifyCode;
          if boNo then
            Inc(m_VerifyCodeInfo.nCurErrorOrd)
          else
            m_VerifyCodeInfo.nCurErrorOrd := 0;
          m_sScriptParam[0] := IntToStr(m_VerifyCodeInfo.nCurErrorOrd);
          m_sScriptParam[1] := BoolToIntStr(boOutTime);
          NPC.GotoLable(Self, m_VerifyCodeInfo.sNextLabel, False);
          m_VerifyCodeInfo.nCurErrorOrd := StrToInt(m_sScriptParam[0]);
        except
        end;
      end;
    end;
  end;
end;


procedure TPlayObject.Run();
var
  tObjCount                             : Integer;
  nInteger                              : Integer;
  ProcessMsg                            : TProcessMessage;
  boInSafeArea                          : Boolean;
  boNeedRecalc                          : Boolean;
  i                                     : Integer;
  nCount                                : Integer;
  boOldHasbox                           : Boolean;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  PlayObject                            : TPlayObject;
  boTakeItem                            : Boolean;
  Castle                                : TUserCastle;
  sTmpLabel                             : string;
  TmpNpc                                : TNormNpc;
  NowTick                               : DWORD;
  DelayCall                             : pTDelayCall;
  ArrowRec                              : pTArrowRec;
  nc, nX, nY                                : Integer;
  nCheckCode                            : Integer;
  tm                                    : DWORD;

resourcestring
  sPayMentExpire                        = '您的帐户充值时间已到期!!!';
  sDisConnectMsg                        = '游戏被强行中断!!!';
  sExceptionMsg1                        = '[Exception] TPlayObject::Run -> Operate 1 Code=%d';
  sExceptionMsg2                        = '[Exception] TPlayObject::Run -> Operate 2 Code=%d # Map:%s(%d,%d)%s Ident:%d Sender:%d wP:%d nP1:%d nP2:%d np3:%d Msg:%s DeMsg:%s';
  sExceptionMsg3                        = '[Exception] TPlayObject::Run -> GetHighHuman';
  sExceptionMsg4                        = '[Exception] TPlayObject::Run -> ClearObj';
  sExceptionMsg5                        = '[Exception] TPlayObject::Run -> AutoGetExpPoint';
  sArrowExcept                          = 'TPlayObject::Run 执行SetArrow列表出错:';
  sCheckItemExcept                      = 'TPlayObject::Run 非法物品检测出错';
  sExceptionMsg6                        = '[Exception] TPlayObject::Run -> 天关幻镜 ';
  sExceptionMsg7                        = '[Exception] TPlayObject::Run -> 减少镇魔值';
  sExpRateNorm                          = '经验倍数恢复正常...';
  sExpLoitRateNorm                      = '功勋倍数恢复正常...';
  sPowerRateNorm                        = '攻击力倍数恢复正常...';
  sDefenceRateNorm                      = '防御力倍数恢复正常...';
  sBurstRateNorm                        = '杀怪爆率恢复正常...';
  sExpRepressDemonRateNorm                 = '镇魔珠经验倍数回叙正常...';
begin
  if g_boExitServer then begin
    m_boOfflineGetGamePoint := False;
    m_boReconnection := False;
    m_boEmergencyClose := True;
  end;
  boNeedRecalc := False;

  NowTick := GetTickCount;
  try
    if m_boDealing then begin                                                                       //正在交易
      if (m_DealCreat = Self) or (m_DealCreat = nil) or (m_btAttatckMode <> HAM_PEACE) or (m_boOfflineGetGamePoint) then
        DealCancel();
    end;

    if (not m_boDeath) then begin
      //召唤烈火结束
      if m_boFireHitSkill and ((NowTick - m_dwLatestFireHitTick) > 20 * 1000) then begin
        m_boFireHitSkill := False;
        SysMsg(sSpiritsGone, c_Red, t_Hint);
        SendSocket(nil, '+UFIR');
      end;

      //召唤雷电结束
      if m_bo44Skill and ((NowTick - m_dwLatest44HitTick) > 20 * 1000) then begin
        m_bo44Skill := False;
        SysMsg(sThunderGone, c_Red, t_Hint);
        SendSocket(nil, '+UTHU');
      end;

      //清空元气
      if (m_wVitaLity >= 1000) and ((NowTick - m_dwClearVitaLityTick) > g_Config.nClearVitaLityTime * 1000) then begin
        DamageVitaLity(1000);
        m_dwClearVitaLityTick := NowTick;
      end;

      if m_boTimeRecall and (NowTick > m_dwTimeRecallTick) then begin
        m_boTimeRecall := False;
        SpaceMove(m_sMoveMap, m_nMoveX, m_nMoveY, 0, nil);
      end;

      //检查是否有重叠人物,有的话要走开
      if ((NowTick - m_dwCheckDupObjTick) > 3000) and (not m_boGodCallBoss) then begin              //如果在神之召唤状态则不检测重叠
        m_dwCheckDupObjTick := NowTick;
        GetStartPoint();                                                                            //重新计算回城点
        tObjCount := m_PEnvir.GetXYObjCount(m_nCurrX, m_nCurrY);
        if tObjCount >= 2 then begin
          if not m_boDupObj then begin
            m_boDupObj := True;
            m_dwDupObjTick := NowTick;
          end;
        end else begin
          m_boDupObj := False;
        end;

        if m_boDupObj and ((NowTick - m_dwDupObjTick) > 1000) then begin
          m_dwDupObjTick := NowTick;
          if (m_wShopItemCount = 0) and (not m_boOfflineGetGamePoint) then
            CharPushed(Random(8), 1, False);
        end;
      end;

      //元神移动到玩家身边去
      if (m_PneumaObject <> nil) and m_boPneuma then begin
        if (m_TargetCret = nil) or (m_TargetCret.m_boGhost) then begin
          m_PneumaObject.GetRightPosition(nX, nY);
          if (abs(m_nTargetX - nX) > 1) or (abs(m_nTargetY - nY) > 1) then begin
            m_nTargetX := nX;
            m_nTargetY := nY;
          end;
          if ((m_PEnvir <> m_PneumaObject.m_PEnvir) or
            (abs(m_nCurrX - m_PneumaObject.m_nCurrX) > 20) or
            (abs(m_nCurrY - m_PneumaObject.m_nCurrY) > 20)) then begin
            SpaceMove(m_PneumaObject.m_PEnvir.m_sMapName, m_nTargetX, m_nTargetY, 0, nil);
            SendRefMsg(RM_TURN,
              m_btDirection,
              m_nCurrX,
              m_nCurrY,
              CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP),
              GetShowName);
          end;
        end;
      end;

      Castle := g_CastleManager.InCastleWarArea(Self);                                              //当前所在的城堡
      if (Castle <> nil) and Castle.m_boUnderWar then begin                                         //城堡正在战斗
        ChangePKStatus(True);
        //如果当前在摆摊,则强制收摊
        if m_wShopItemCount > 0 then begin
          CancelDoShop;
        end;
      end;

      if (NowTick - dwTick578) > 1000 then begin
        dwTick578 := NowTick;
        //行会战争名字颜色
        if (m_MyGuild <> nil) then begin
          if TGuild(m_MyGuild).m_GuildWarList.Count > 0 then begin
            boInSafeArea := InSafeArea();
            if boInSafeArea <> m_boInSafeArea then begin
              m_boInSafeArea := boInSafeArea;
              RefNameColor();
            end;
          end;
        end;

        //进出安全区提示
        if (not m_boPneuma) then begin
          if g_Config.boSafeAreaHint and (GetTickCount - m_dwCheckSafeArea > 2000) then begin
            m_dwCheckSafeArea := GetTickCount;
            boInSafeArea := InSafeZone;
            if boInSafeArea <> m_boInSafezone then begin
              m_boInSafezone := boInSafeArea;
              if m_boInSafezone then
                SysMsg('您已经进入安全区...', c_Red, t_Hint)
              else
                SysMsg('您已经离开安全区...', c_Red, t_Hint);
            end;
          end;
        end;

        if (Castle <> nil) and Castle.m_boUnderWar then begin                                       //攻城战
          if (m_PEnvir = Castle.m_MapPalace) and (m_MyGuild <> nil) then begin                      //在皇宫
            if not Castle.IsMember(Self) then begin                                                 //不是当前城堡的人
              if Castle.IsAttackGuild(TGuild(m_MyGuild)) then begin                                 //攻城方
                if Castle.CanGetCastle(TGuild(m_MyGuild)) then begin                                //是否攻下
                  Castle.GetCastle(TGuild(m_MyGuild));
                  UserEngine.SendServerGroupMsg(SS_211, g_Config.nServerNumber,
                    TGuild(m_MyGuild).sGuildName);
                  if Castle.InPalaceGuildCount <= 1 then Castle.StopWallconquestWar();
                  //如果攻城行会只有一个,则结束战斗
                end;
              end;
            end;
          end;
        end else begin
          ChangePKStatus(False);
        end;

        if m_boNameColorChanged then begin
          m_boNameColorChanged := False;
          RefUserState();
          RefShowName();
        end;
      end;

      //人物死亡移到消息处理上面执行
      if (m_WAbil.dwHP = 0) then begin
        if (m_UseItems[U_DRESS].wIndex > 0) and
          m_UseItems[U_DRESS].IsGod() and
          (m_UseItems[U_DRESS].btValue[15] >= 100) then begin
          m_UseItems[U_DRESS].btValue[15] := 0;
          SendMsg(Self, RM_SENDGODUSEVAL, 1, m_UseItems[U_DRESS].btValue[15], 0, 0, '');
          m_WAbil.dwHP := m_WAbil.dwMaxHP;
          boNeedRecalc := True;
          SysMsg('重塑金身生效,满状态复活', c_Green, t_Hint);
        end else begin
          if (m_boRevivalEx or ((m_LastHiter = nil) or not m_LastHiter.m_boUnRevival) and m_boRevival) and
            (GetTickCount - m_dwRevivalTick > g_Config.dwRevivalTime {60 * 1000}) then begin
            m_dwRevivalTick := NowTick;
            ItemDamageRevivalRing;
            m_WAbil.dwHP := Round(m_WAbil.dwMaxHP * m_nRevivalRate / 100);
            boNeedRecalc := True;
            SendDefMessage(1639, Integer(Self), Round(g_Config.dwRevivalTime / 1000), 0, 0, '');
            SysMsg(g_sRevivalRecoverMsg {'复活戒指生效,体力恢复'}, c_Green, t_Hint);
          end;
        end;
        if m_WAbil.dwHP = 0 then Die;
      end;
    end;
  except
    MainOutMessage(Format(sExceptionMsg1, [0]));
  end;

  //清除摆摊的指针
  if (m_PackPet <> nil) then begin
    if m_PackPet.m_boDeath or m_PackPet.m_boGhost then begin
      m_PackPet := nil;
      m_PetInfo[1].nMakeIndex := 0;
      m_PetInfo[1].wLevel := 0;
      m_PetInfo[1].btType := 0;
      m_PetInfo[1].btReLive := 0;
    end;
  end;

  try                                                                                               //处理人物消息
    nCheckCode := 0;
    m_dwGetMsgTick := GetTickCount;
    while (GetTickCount - m_dwGetMsgTick < g_Config.dwHumanGetMsgTime) and GetMessage(@ProcessMsg) do begin
      nCheckCode := 1;
      if not Operate(@ProcessMsg) then Break;
    end;
    nCheckCode := 2;
    //检查验证码是否超时
    if m_VerifyCodeInfo.pNextNpc <> nil then begin
      if (GetTickCount - m_VerifyCodeInfo.nBeginTick) > m_VerifyCodeInfo.nOutTime then begin
        ClientCheckVerifyCode('', True);
      end;
    end;
    nCheckCode := 3;
    //断线
    if (m_boEmergencyClose or m_boKickFlag or m_boSoftClose) then begin
      if m_boPneuma and (m_PneumaObject <> nil) then begin
        nCheckCode := 4;
        SendRefMsg(RM_510, 1, 0, 42, 0, '');
        //SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
        TPlayObject(m_PneumaObject).m_dwCallPneumaTick := GetTickCount;
        TPlayObject(m_PneumaObject).m_PneumaObject := nil;
        if m_boInosculatePneuma then begin
          m_PneumaObject.SendMsg(m_PneumaObject, RM_CTRLMENTAL, 0, Integer(m_PneumaObject), 259, 0, '');
          //当融合状态下!元神有血是备份到这里的
          TPlayObject(m_PneumaObject).m_InosculatePneumaHP := m_WAbil.dwHP;
          TPlayObject(m_PneumaObject).m_InosculatePneumaMP := m_WAbil.dwMP;
        end;

        //清除元神骑站数据
        TPlayObject(m_PneumaObject).m_PetInfo[3].nMakeIndex := 0;
        TPlayObject(m_PneumaObject).m_PetInfo[3].wLevel := 0;
        TPlayObject(m_PneumaObject).m_PetInfo[3].btType := 0;
        TPlayObject(m_PneumaObject).m_PetInfo[3].btReLive := 0;
        TPlayObject(m_PneumaObject).m_PetInfo[3].btRideFightSpeed := 0;
      end else if m_PneumaObject <> nil then begin                                                  //人物下线,元神也下线
        nCheckCode := 5;
        TPlayObject(m_PneumaObject).m_boSoftClose := True;
        TPlayObject(m_PneumaObject).SendRefMsg(RM_510, 1, 0, 42, 0, '');
        TPlayObject(m_PneumaObject).SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
        if TPlayObject(m_PneumaObject).m_boInosculatePneuma then begin
          //当融合状态下!元神有血是备份到这里的
          m_InosculatePneumaHP := TPlayObject(m_PneumaObject).m_WAbil.dwHP;
          m_InosculatePneumaMP := TPlayObject(m_PneumaObject).m_WAbil.dwMP;
        end;

        m_PneumaObject := nil;
      end;
      nCheckCode := 6;
      if m_boSwitchData then begin
        m_sMapName := m_sSwitchMapName;
        m_nCurrX := m_nSwitchMapX;
        m_nCurrY := m_nSwitchMapY;
      end;
      nCheckCode := 7;
      //触发下线脚本
      if (m_sOffLineLabel <> '') then begin
        ExecuteScript(g_ManageNPC, m_sOffLineLabel);
      end;
      nCheckCode := 8;
      if (not m_boPneuma) and (not g_boExitServer) and (not m_boReconnection) then begin
        ExecuteScript(g_ManageNPC, '@PlayOffLine');                                                 //人物下线触发
      end;
      nCheckCode := 9;
      if (not m_boOfflineGetGamePoint) and (not m_boPneuma) and (not g_boExitServer) and (m_boReconnection) then begin
        ExecuteScript(g_ManageNPC, '@PlayReconnection');                                            //人物小退触发
      end;
      nCheckCode := 10;
      if not m_boOfflineGetGamePoint then begin
        MakeGhost();
      end;
      nCheckCode := 11;
      if m_boKickFlag and not m_boPneuma then begin
        SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
      end;
      nCheckCode := 12;
      if not m_boReconnection and m_boSoftClose and not m_boPneuma then begin
        if not m_boKickUserSessInfo then begin
          m_boKickUserSessInfo := True;
          FrmIDSoc.SendHumanLogOutMsg(m_sUserID, m_nSessionID);
        end;
      end;
    end;
    nCheckCode := 13;
  except
    on E: Exception do begin
      if ProcessMsg.wIdent = 0 then
        MakeGhost();
      // 11.22 加上,用于处理 人物异常退出,但人物还在游戏中问题 提示 Ident0  错误
      if m_PEnvir = nil then
        MainOutMessage(Format(sExceptionMsg2, [nCheckCode, '无效地图', m_nCurrX,
          m_nCurrY, m_sCharName,
            ProcessMsg.wIdent,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.wParam,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)
            ]))
      else
        MainOutMessage(Format(sExceptionMsg2, [nCheckCode, m_PEnvir.m_sMapName, m_nCurrX,
          m_nCurrY, m_sCharName,
            ProcessMsg.wIdent,
            Integer(ProcessMsg.BaseObject),
            ProcessMsg.wParam,
            ProcessMsg.nParam1,
            ProcessMsg.nParam2,
            ProcessMsg.nParam3,
            ProcessMsg.sMsg,
            DeCodeString(ProcessMsg.sMsg)
            ]));
      MainOutMessage(E.Message);
    end;
  end;

  {夺宝系统}
  try
    nCheckCode := 100;
    i := 0;
    nCount := m_ArrowList.Count;
    while i < m_ArrowList.Count do begin
      nCheckCode := 101;
      ArrowRec := pTArrowRec(m_ArrowList.Objects[i]);
      nCheckCode := 102;
      //检查是否到了最后时间
      if ArrowRec.dwEndCheckTime <= GetTickCount then begin
        nCheckCode := 103;
        ExecuteScript(g_FunctionNPC, ArrowRec.sEndLabel);
        nCheckCode := 104;
        if nCount = m_ArrowList.Count then begin                                                    //防止脚本删除任务
          nCheckCode := 105;
          m_ArrowList.Delete(i);
          nCheckCode := 106;
          Dispose(ArrowRec);
        end else
          Break;
      end else if ArrowRec.dwCheckTime <= GetTickCount then begin
        nCheckCode := 107;
        ExecuteScript(g_FunctionNPC, ArrowRec.sCheckLabel);
        if nCount <> m_ArrowList.Count then Break;                                                  //防止脚本删除任务
        nCheckCode := 108;
        ArrowRec.dwCheckTime := ArrowRec.dwCheckTime + ArrowRec.dwCheckInterval;
      end;
      Inc(i);
    end;
    boOldHasbox := m_boArrow;
    if (nCount > 0) and (m_ArrowList.Count = 0) then begin                                          //取消了所有标签
      m_boArrow := False;
      for i := m_ItemList.Count - 1 downto 0 do begin                                               //检测包裹中是否有宝盒
        UserItem := pTUserItem(m_ItemList[i]);
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem = nil then Continue;
        if CheckSPCode(StdItem.Reserved, RE_TREASURE) then begin
          m_boArrow := True;
          Break;
        end;
      end;
    end else
      m_boArrow := m_ArrowList.Count > 0;
    if boOldHasbox <> m_boArrow then begin
      m_nCharStatus := GetCharStatus();
      StatusChanged();
    end;
  except
    on E: Exception do
      MainOutMessage(sArrowExcept + IntToStr(nCheckCode) + ' ' + E.Message);
  end;

  try
    //检查身上的装备有没不符合
    if (not m_boDeath) then begin
      for i := Low(THumItems) to High(THumItems) do begin
        if m_UseItems[i].wIndex > 0 then begin
          StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
          if StdItem <> nil then begin
            if not CheckItemsNeed(StdItem) then begin
              boTakeItem := False;                                                                  //0419
              New(UserItem);
              UserItem^ := m_UseItems[i];
              if AddItemToBag(UserItem) then begin
                SendAddItem(UserItem);
                WeightChanged();
                SysMsg('物品 ' + StdItem.Name + ' 已经自动取下。', c_Red, t_Hint);
                boTakeItem := True;
              end else begin
                Dispose(UserItem);
                if DropItemDown(@m_UseItems[i], 2, False, nil, Self) then begin
                  SysMsg('物品 ' + StdItem.Name + ' 自动取下失败,已丢弃。', c_Red, t_Hint);
                  boTakeItem := True;
                end;
              end;
              if boTakeItem then begin
                SendDelItems(@m_UseItems[i]);
                m_UseItems[i].wIndex := 0;
                RecalcAbilitys(True);
              end;
            end;
          end else begin
            SendDelItems(@m_UseItems[i]);
            m_UseItems[i].wIndex := 0;
            RecalcAbilitys(True);
          end;
        end;
      end;
    end;
  except
    on E: Exception do
      MainOutMessage(sCheckItemExcept + E.Message);
  end;
   if (m_DealCreat <> nil) and (m_DealCreat.m_boGhost) then m_DealCreat := nil;            //交易方死亡
  if (m_dwEatTalismanTick > 0) and (NowTick > m_dwEatTalismanTick) then begin
    m_dwEatTalismanTick := 0;
    SysMsg('辟邪丹效果已经消失,你将无法抵御魔气侵袭', c_Red, t_Hint);
    ExecuteScript(g_FunctionNPC, '@辟邪丹失效');
  end;

  if (not m_boDeath) then begin
    tObjCount := m_nGameGold;
    //自动减元宝
    if m_boDecGameGold and (NowTick - m_dwDecGameGoldTick > m_dwDecGameGoldTime) then begin
      m_dwDecGameGoldTick := NowTick;
      if m_nGameGold >= m_nDecGameGold then begin
        Dec(m_nGameGold, m_nDecGameGold);
        nInteger := m_nDecGameGold;
      end else begin
        nInteger := m_nGameGold;
        m_nGameGold := 0;
        m_boDecGameGold := False;
        MoveToHome();                                                                               //没有元宝可减了,就让他回城
      end;
      if g_boGameLogGameGold then begin
        AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD, m_sMapName, m_nCurrX,
          m_nCurrY, m_sCharName, g_Config.sGameGoldName, nInteger, '-', 'Auto']));
      end;
    end;

    //自动加元宝
    if m_boIncGameGold and (NowTick - m_dwIncGameGoldTick > m_dwIncGameGoldTime) then begin
      m_dwIncGameGoldTick := NowTick;
      if m_nGameGold + m_nIncGameGold < g_Config.nHumanMaxGameGold {2000000} then begin
        Inc(m_nGameGold, m_nIncGameGold);
        nInteger := m_nIncGameGold;
      end else begin
        m_nGameGold := g_Config.nHumanMaxGameGold;
        nInteger := g_Config.nHumanMaxGameGold - m_nGameGold;
        m_boIncGameGold := False;
      end;
      if g_boGameLogGameGold then begin
        AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD, m_sMapName, m_nCurrX,
          m_nCurrY, m_sCharName, g_Config.sGameGoldName, nInteger, '+', 'Auto']));
      end;
    end;

    //当前环境自动减元宝
    if not m_boDecGameGold and m_PEnvir.m_MapFlag.boDecGameGold then begin
      if NowTick - m_dwDecGameGoldTick > LongWord(m_PEnvir.m_MapFlag.nDECGAMEGOLDTIME * 1000) then begin
        m_dwDecGameGoldTick := NowTick;
        if m_nGameGold >= m_PEnvir.m_MapFlag.nDecGameGold then begin
          Dec(m_nGameGold, m_PEnvir.m_MapFlag.nDecGameGold);
          nInteger := m_PEnvir.m_MapFlag.nDecGameGold;
        end else begin
          nInteger := m_nGameGold;
          m_nGameGold := 0;
          m_boDecGameGold := False;
          MoveToHome();
        end;
        if g_boGameLogGameGold then begin
          AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD, m_sMapName,
            m_nCurrX, m_nCurrY, m_sCharName, g_Config.sGameGoldName, nInteger, '-', 'Map']));
        end;
      end;
    end;
    //当前环境自动加元宝
    if not m_boIncGameGold and m_PEnvir.m_MapFlag.boIncGameGold then begin
      if NowTick - m_dwIncGameGoldTick > LongWord(m_PEnvir.m_MapFlag.nINCGAMEGOLDTIME * 1000) then begin
        m_dwIncGameGoldTick := NowTick;
        if m_nGameGold + m_PEnvir.m_MapFlag.nIncGameGold <= g_Config.nHumanMaxGameGold then begin
          Inc(m_nGameGold, m_PEnvir.m_MapFlag.nIncGameGold);
          nInteger := m_PEnvir.m_MapFlag.nIncGameGold;
        end else begin
          nInteger := g_Config.nHumanMaxGameGold - m_nGameGold;
          m_nGameGold := g_Config.nHumanMaxGameGold;
        end;
        if g_boGameLogGameGold then begin
          AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEGOLD, m_sMapName,
            m_nCurrX, m_nCurrY, m_sCharName, g_Config.sGameGoldName, nInteger, '+', 'Map']));
        end;
      end;
    end;
    //发送元宝增加消息
    if tObjCount <> m_nGameGold then GameGoldChanged();

    //当前环境自动加游戏点
    if m_PEnvir.m_MapFlag.boINCGAMEPOINT then begin
      if (NowTick - m_dwIncGamePointTick > LongWord(m_PEnvir.m_MapFlag.nINCGAMEPOINTTIME * 1000)) then begin
        m_dwIncGamePointTick := NowTick;
        if m_nGamePoint + m_PEnvir.m_MapFlag.nINCGAMEPOINT <= 2000000 then begin
          Inc(m_nGamePoint, m_PEnvir.m_MapFlag.nINCGAMEPOINT);
          nInteger := m_PEnvir.m_MapFlag.nINCGAMEPOINT;
        end else begin
          m_nGamePoint := 2000000;
          nInteger := 2000000 - m_nGamePoint;
        end;
        if g_boGameLogGamePoint then begin
          AddGameDataLog(Format(g_sGameLogMsg, [LOG_GAMEPOINT, m_sMapName,
            m_nCurrX, m_nCurrY, m_sCharName, g_Config.sGamePointName, nInteger, '+', 'Map']));
        end;
      end;
    end;
    //减血
    if m_PEnvir.m_MapFlag.boDECHP and (m_dwEatTalismanTick = 0) and (NowTick - m_dwDecHPTick > LongWord(m_PEnvir.m_MapFlag.nDECHPTIME * 1000)) then begin
      m_dwDecHPTick := NowTick;
      if m_WAbil.dwHP > m_PEnvir.m_MapFlag.nDECHPPOINT then begin
        Dec(m_WAbil.dwHP, m_PEnvir.m_MapFlag.nDECHPPOINT);
      end else begin
        m_WAbil.dwHP := 0;
      end;

      boNeedRecalc := True;
    end;

    //加血
    if m_PEnvir.m_MapFlag.boINCHP and (NowTick - m_dwIncHPTick > LongWord(m_PEnvir.m_MapFlag.nINCHPTIME * 1000)) then begin
      m_dwIncHPTick := NowTick;
      if m_WAbil.dwHP + m_PEnvir.m_MapFlag.nDECHPPOINT < m_WAbil.dwMaxHP then begin
        Inc(m_WAbil.dwHP, m_PEnvir.m_MapFlag.nDECHPPOINT);
      end else begin
        m_WAbil.dwHP := m_WAbil.dwMaxHP;
      end;
      boNeedRecalc := True;
    end;
  end;

  //地图延迟跳转
  if m_PEnvir.m_MapFlag.boDelayGoto and (GetTickCount - m_dwDelayGotoTick > LongWord(m_PEnvir.m_MapFlag.nDelayGotoTime * 1000)) then begin
    m_dwDelayGotoTick := NowTick;
    if m_PEnvir.m_MapFlag.sDelayGotoLable <> '' then ExecuteScript(g_ManageNPC, m_PEnvir.m_MapFlag.sDelayGotoLable);
  end;

  //降饥饿点
  if (not m_boDeath) and g_Config.boHungerSystem and ((NowTick - m_dwDecHungerPointTick) > 1000) then begin
    m_dwDecHungerPointTick := NowTick;
    if m_nHungerStatus > 0 then begin
      tObjCount := GetMyStatus();
      Dec(m_nHungerStatus);
      if tObjCount <> GetMyStatus() then
        RefMyStatus();
    end else if g_Config.boHungerDecHP then begin
      //减少涨HP,MP
      Dec(m_nHealthTick, 60);
      Dec(m_nSpellTick, 10);
      m_nSpellTick := _Max(0, m_nSpellTick);
      Dec(m_nPerHealth);
      Dec(m_nPerSpell);

      if m_WAbil.dwHP > m_WAbil.dwHP div 100 then begin
        Dec(m_WAbil.dwHP, _Max(1, m_WAbil.dwHP div 100));
      end else begin
        if m_WAbil.dwHP <= 2 then m_WAbil.dwHP := 0;
      end;
      boNeedRecalc := True;
    end;
  end;

  if boNeedRecalc then HealthSpellChanged();

  try
    if (not m_boDeath) and (m_nHuanjingIdx <> 0) and (m_dwHuanjingTick + g_Config.nHuanjingDecLingli < NowTick) then begin
      m_dwHuanjingTick := NowTick;
      for i := m_ItemList.Count - 1 downto 0 do begin
        UserItem := pTUserItem(m_ItemList[i]);
        if UserItem.MakeIndex = m_nHuanjingIdx then begin
          if UserItem.Dura > 0 then Dec(UserItem.Dura);
          if UserItem.Dura = 2 then
            SysMsg('幻镜中的灵力即将消耗殆尽,如不及时补充幻镜就将碎裂', c_Red, t_Hint);
          if (UserItem.Dura = 0) then begin
            UserItem.btValue[1] := 1;
            tm := MakeLong(MakeWord(UserItem.btValue[2], UserItem.btValue[3]),
              MakeWord(UserItem.btValue[4], UserItem.btValue[5]));
            if tm = 0 then
              m_sScriptParam[0] := '1'                                                              //领取次数
            else
              m_sScriptParam[0] := IntToStr((DateTimeToWolTIme(Now) - tm + 1) div g_Config.nHuanjingGetGift);
            m_sScriptParam[1] := IntToStr(UserItem.Dura);                                           //幻境灵力
            m_sScriptParam[2] := IntToStr(UserItem.btValue[1]);
            //幻境状态 0正常 1破碎
            m_sScriptParam[3] := m_PEnvir.m_sMapName;                                               //地图名
            m_sScriptParam[4] := IntToStr(UserItem.btValue[0]);
            //幻境镶嵌宝石类型  1 2 3 表示   0普通幻境
            m_sScriptParam[5] := IntToStr(UserItem.MakeIndex);                                      //幻境ID
            ExecuteScript(g_FunctionNPC, '@天关幻镜奖励');
            SendDefMessage(34980, 0, 769, 300, 3000, '');
            m_nHuanjingIdx := 0;
          end;
          SendUpdateItem(UserItem);
          SendDefMessage(34980, UserItem.MakeIndex, 769, 300, 3000, '');
          Break;
        end;
      end;
    end;
  except
    on E: Exception do
      MainOutMessage(sExceptionMsg6 + E.Message);
  end;

  if (not m_boDeath) and (NowTick - m_dwDecAntvPowerTick > 60 * 1000) then begin
    m_dwDecAntvPowerTick := NowTick;
    try
      for i := Low(THumItems) to High(THumItems) do begin
        if (m_UseItems[i].wIndex > 0) then begin
          if (m_UseItems[i].Evil.MakeIndex <> 0) and (m_UseItems[i].Evil.sName <> '') then begin
            if (m_UseItems[i].Evil.wPower - g_Config.nAntiEvilPowerDecSpeed) < 0 then
              m_UseItems[i].Evil.wPower := 0
            else
              Dec(m_UseItems[i].Evil.wPower, g_Config.nAntiEvilPowerDecSpeed);
            if m_UseItems[i].Evil.wPower < 10 then begin
              if m_UseItems[i].Evil.wPower <= 0 then begin
                FillChar(m_UseItems[i].Evil, SizeOf(TEvil), #0);
                SendUpdateItem(@m_UseItems[i]);
                SendDefMessage(SM_ITEMEVIL, Integer(Self), LoWord(m_UseItems[i].MakeIndex), HiWord(m_UseItems[i].MakeIndex), 0, '');
                StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
                if (StdItem <> nil) then
                  SysMsg(Format('你的%s镇魔值随着时间渐渐变弱,%s上的心魔已经逃逸。', [StdItem.FilterName, StdItem.FilterName]), c_Red, t_Hint);
                // RecalcLevelAbilitys();
                RecalcAbilitys();
                SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
                SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
              end else
                SysMsg('你装备中的心魔' + m_UseItems[i].Evil.sName + '即将逃逸,请使用镇魔符增加镇魔值', c_Red, t_Hint);
            end;
            SendDefMessage(SM_ANTIEVILPOWER, m_UseItems[i].MakeIndex, m_UseItems[i].Evil.wPower, i, 0, '');
          end;

          //神兵宝甲神力值增加//////
          if m_UseItems[i].IsGod and
            (((m_UseItems[i].btItemExt[20] < 100) and (i = U_WEAPON)) or
            ((m_UseItems[i].btValue[15] < 100) and (i = U_DRESS))) then begin
            Inc(m_UseItems[i].btValue[17]);
            if (m_UseItems[i].btValue[17] >= m_UseItems[i].btValue[18]) then begin
              m_UseItems[i].btValue[17] := 0;
              if (i = U_DRESS) then begin
                m_UseItems[i].btValue[15] := _MIN(m_UseItems[i].btValue[15] + m_UseItems[i].God_UseVal, 100);
                SendGodUseVal(1, m_UseItems[i].btValue[15]);
              end else if (i = U_WEAPON) and (m_UseItems[i].btValue[15] = 0) then begin
                m_UseItems[i].btItemExt[20] := _MIN(m_UseItems[i].btItemExt[20] + m_UseItems[i].btValue[19], 100);
                SendGodUseVal(0, m_UseItems[i].btItemExt[20]);
                if m_UseItems[i].btItemExt[20] >= 100 then begin
                  m_UseItems[i].btValue[15] := 1;
                  SysMsg('您处于暴走模式,接下来的攻击将会暴击', c_Red, t_Hint);
                end;
              end;
            end;
          end;                                                                                      //if m_UseItems[i].IsGod and (m_UseItems[i].btItemExt[20] < 100) then begin

        end;
      end;
    except
      on E: Exception do
        MainOutMessage(sExceptionMsg7 + E.Message);
    end;
  end;

  if (not m_boDeath) and (NowTick - m_dwRateTick > 1000) then begin
    m_dwRateTick := NowTick;
    //检测元神和自己是否处于同一个地图
    if m_boPneuma and (m_PneumaObject <> nil) and not (m_PneumaObject.m_boDeath or m_PneumaObject.m_boGhost) and
      ((m_PneumaObject.m_PEnvir <> m_PEnvir) or
      (abs(m_nCurrX - m_PneumaObject.m_nCurrX) > 15) or
      (abs(m_nCurrY - m_PneumaObject.m_nCurrY) > 15)) then begin

      SendMsg(Self, CM_3079, 0, 0, 0, 0, '');
    end;

    if m_dwButchItemTime > 0 then begin
      Dec(m_dwButchItemTime);
      if (m_dwButchItemTime = 0) and (m_ButchItem.BaseObject > 0) and (m_ButchItem.PlayObject > 0) then begin
        g_PacketManage3.Init;
        g_PacketManage3.WriteInteger(m_ButchItem.PlayObject);
        g_PacketManage3.WriteInteger(m_ButchItem.BaseObject);
        g_PacketManage3.WriteInteger(0);
        g_PacketManage3.WriteInteger($05);
        g_PacketManage3.WriteByte(1);
        g_PacketManage3.WriteByte(m_btDirection);
        g_PacketManage3.FillWrite(5, 0);
        g_PacketManage3.WriteByte(1);
        SendDefMessage(2161, Integer(self), 0, 0, 0, g_PacketManage3.GetMsg, True);
        m_sScriptParam[0] := TBaseObject(m_ButchItem.BaseObject).m_sCharName;
        ExecuteScript(g_FunctionNPC, '@采集结束_' + IntToStr(m_ButchItem.nID));
        if TBaseObject(m_ButchItem.BaseObject).m_Abil.MAC > 0 then
          TBaseObject(m_ButchItem.BaseObject).Die;            
      end;
    end;

    if m_dwKillMonExpRateTime > 0 then begin
      Dec(m_dwKillMonExpRateTime);
      if m_dwKillMonExpRateTime = 0 then begin
        m_nKillMonExpRate := 100;
        SysMsg(sExpRateNorm, c_Red, t_Hint);
      end;
    end;

    if m_dwKillMonExpLoitRateTime > 0 then begin
      Dec(m_dwKillMonExpLoitRateTime);
      if m_dwKillMonExpLoitRateTime = 0 then begin
        m_nKillMonExpLoitRate := 100;
        SysMsg(sExpLoitRateNorm, c_Red, t_Hint);
      end;
    end;

    if m_dwKillMonRepressDemonRateTime > 0 then begin
      Dec(m_dwKillMonRepressDemonRateTime);
      if m_dwKillMonRepressDemonRateTime = 0 then begin
        m_nKillMonRepressDemonRate := 100;
        SysMsg(sExpRepressDemonRateNorm, c_Red, t_Hint);
      end;
    end;

    if m_dwKillMonBurstRateTime > 0 then begin
      Dec(m_dwKillMonBurstRateTime);
      if m_dwKillMonBurstRateTime = 0 then begin
        m_nKillMonBurstRate := 100;
        SysMsg(sBurstRateNorm, c_Red, t_Hint);
      end;
    end;

    if m_dwPowerRateTime > 0 then begin
      Dec(m_dwPowerRateTime);
      if m_dwPowerRateTime = 0 then begin
        m_nPowerRate := 100;
        SysMsg(sPowerRateNorm, c_Red, t_Hint);
      end;
    end;

    if m_dwDefenceRateTime > 0 then begin
      Dec(m_dwDefenceRateTime);
      if m_dwDefenceRateTime = 0 then begin
        m_nDefenceRate := 100;
        SysMsg(sDefenceRateNorm, c_Red, t_Hint);
      end;
    end;
  end;

  //新增BUFF计时处理效果
  if m_btRaceServer = RC_PLAYOBJECT then
  begin
    for i := Low(m_btBuffArr) to High(m_btBuffArr) do begin
      if m_btBuffArr[i] > 0 then begin
        if NowTick > (m_dwBuffArrTick[i]) then begin
          m_btBuffArr[i] := 0;
          m_sScriptParam[30] := IntToStr(i);
          ExecuteScript(g_FunctionNPC, '@_结束_CHANGEMODE');
          case i of                                                                                 //
            1: begin
                m_boAdminMode := False;                                                             //管理员模式
                if g_Config.boShowScriptActionMsg then begin
                  if m_boAdminMode then
                    SysMsg(sGameMasterMode, c_Green, t_Hint)
                  else
                    SysMsg(sReleaseGameMasterMode, c_Green, t_Hint);
                end;
              end;
            2: begin
                m_boSuperMan := False;                                                              //无敌模式
                if g_Config.boShowScriptActionMsg then begin
                  if m_boSuperMan then
                    SysMsg(sSupermanMode, c_Green, t_Hint)
                  else
                    SysMsg(sReleaseSupermanMode, c_Green, t_Hint);
                end;
              end;
            3: begin
                m_boObMode := False;                                                                //隐身模式
                if g_Config.boShowScriptActionMsg then begin
                  if m_boObMode then
                    SysMsg(sObserverMode, c_Green, t_Hint)
                  else
                    SysMsg(g_sReleaseObserverMode, c_Green, t_Hint);
                end;
              end;
            4: begin
                m_boNoAttackMode := False;                                                          //禁止攻击模式
                if g_Config.boShowScriptActionMsg then begin
                  if m_boNoAttackMode then
                    SysMsg(sNoAttackMode, c_Green, t_Hint)
                  else
                    SysMsg(sCanAttackMode, c_Green, t_Hint);
                end;
              end;
            5: begin
                m_boParalysisMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boParalysisMode then
                    SysMsg('进入麻痹状态', c_Red, t_Hint)
                  else
                    SysMsg('退出麻痹状态', c_Red, t_Hint);
                end;
              end;
            6: begin
                m_boUnParalysisMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boUnParalysisMode then
                    SysMsg('进入防麻痹状态', c_Red, t_Hint)
                  else
                    SysMsg('退出防麻痹状态', c_Red, t_Hint);
                end;
              end;
            7: begin
                m_boMagicShieldMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boMagicShieldMode then
                    SysMsg('进入护体状态', c_Red, t_Hint)
                  else
                    SysMsg('退出护体状态', c_Red, t_Hint);
                end;
              end;
            8: begin
                m_boUnMagicShieldMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boUnMagicShieldMode then
                    SysMsg('进入防护体状态', c_Red, t_Hint)
                  else
                    SysMsg('退出防护体状态', c_Red, t_Hint);
                end;
              end;
            9: begin
                m_boRevivalMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boRevivalMode then
                    SysMsg('进入重生状态', c_Red, t_Hint)
                  else
                    SysMsg('退出重生状态', c_Red, t_Hint);
                end;
              end;
            10: begin
                m_boUnRevivalMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boUnRevivalMode then
                    SysMsg('进入防重生状态', c_Red, t_Hint)
                  else
                    SysMsg('退出防重生状态', c_Red, t_Hint);
                end;
              end;
            11: begin
                m_boParalysisModeEx := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boParalysisModeEx then
                    SysMsg('进入超级麻痹状态', c_Red, t_Hint)
                  else
                    SysMsg('退出超级麻痹状态', c_Red, t_Hint);
                end;
              end;
            12: begin
                m_boMagicShieldModeEx := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boMagicShieldModeEx then
                    SysMsg('进入超级护体状态', c_Red, t_Hint)
                  else
                    SysMsg('退出超级护体状态', c_Red, t_Hint);
                end;
              end;
            13: begin
                m_boRevivalModeEx := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boRevivalModeEx then
                    SysMsg('进入超级重生状态', c_Red, t_Hint)
                  else
                    SysMsg('退出超级重生状态', c_Red, t_Hint);
                end;
              end;
            14: begin                                                                               //隐身模式
                m_boHideModeEx := False;
                m_wStatusTimeArr[STATE_TRANSPARENT] := 1;
                m_nCharStatus := GetCharStatus();
                StatusChanged();
              end;
            15: begin
                m_wStatusTimeArr[POISON_DONTMOVE] := 1;
                m_nMagicStatus := GetMagicStatus();
                Status2Changed();
              end;
            16: begin                                                                               //被麻痹
                m_wStatusTimeArr[POISON_STONE] := 1;
                m_nCharStatus := GetCharStatus();
                StatusChanged();
              end;
            17: begin
                m_boMcParalysisMode := False;
                if g_Config.boShowScriptActionMsg then begin
                  if m_boMcParalysisMode then
                    SysMsg('进入魔道麻痹状态', c_Red, t_Hint)
                  else
                    SysMsg('退出魔道麻痹状态', c_Red, t_Hint);
                end;
              end;
            18: begin
                m_boNeedKneel := False;
                SendRefMsg(RM_TURNTO, 0, 0, 0, 0, '');
              end;
            19: begin
                m_btRulerLevel := 0;
                FeatureChanged;
                SendRefMsg(RM_TURN,
                  m_btDirection,
                  m_nCurrX,
                  m_nCurrY,
                  CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP),
                  GetShowName);
              end;
            20: begin
                m_boUnWater := False;
                if m_boRideOn then begin
                  if not CheckMapRideOn(m_PEnvir) then ClientRideOff;
                end;
              end;
            21: begin
                m_boHasBaGua := False;
                FeatureChanged;
              end;
            22: m_boStickMode := False;
            23: m_boRideDragonMode := False;
            24: m_boCanGetBackItem := True;
            25: m_boCanRun := True;
            26: m_boCanWalk := True;
            27: m_boCanDeal := True;
            28: m_boCanDrop := True;
            29: m_boCanUseItem := True;
            30: m_boCanHit := True;
            31: m_boCanSpell := True;
            32: begin
                m_boOfficerGodWings := False;
                FeatureChanged;
              end;
            33: begin
                m_btWalkLotus := 0;
                StatusChanged();
              end;
            34: begin
                m_boVehicleMaterial := False;
                StatusChanged();
              end;
            35: m_boRideOrthrusMode := False;
            36: begin
                m_btLoverTitle := 0;
                FeatureChanged;
              end;
            37: begin
                m_boSoaring := False;
                FeatureChanged;
              end;
            38: begin
                m_boGameManage := False;
                FeatureChanged;
              end;
            39: begin
                m_boFirstCarpenter := False;
                FeatureChanged;
              end;
            40: begin
                m_btColorSkill := 0;
                FeatureChanged;
              end;
            41: begin
                m_btKingTitle := 0;
                FeatureChanged;
              end;
            42: begin
                m_btLoverEvents := 0;
                StatusChanged();
              end;
            43: begin
                m_boBianShen := False;
                m_wBianshenImg := 0;
                m_wBianshenAppr := 0;
                m_boAttackMode := False;
                StatusChanged();
              end;
            44: begin
                m_HumanDisarm.boDisarm := False;
                m_HumanDisarm.nTime := 0;
                m_HumanDisarm.btRate := 0;
              end;
            45: begin
                m_boUnMcParalysis := false;
              end;
            46: begin
                m_boUnSafeZone := false;
              end;
            47: begin
                m_boRulerhalo := false;
                StatusChanged();
              end;
          end;
          if i > 4 then RecalcAbilitys;
        end;
      end;
    end;
  end;


  try                                                                                               //取得在线最高等级、PK、攻击力、魔法、道术 的人物
    if (g_HighLevelHuman = Self) and (m_boDeath or m_boGhost) then g_HighLevelHuman := nil;
    if (g_HighPKPointHuman = Self) and (m_boDeath or m_boGhost) then g_HighPKPointHuman := nil;
    if (g_HighDCHuman = Self) and (m_boDeath or m_boGhost) then g_HighDCHuman := nil;
    if (g_HighMCHuman = Self) and (m_boDeath or m_boGhost) then g_HighMCHuman := nil;
    if (g_HighSCHuman = Self) and (m_boDeath or m_boGhost) then g_HighSCHuman := nil;
    if (g_HighOnlineHuman = Self) and (m_boDeath or m_boGhost) then g_HighOnlineHuman := nil;

    if (m_btPermissionGM < 6) and not m_boDeath and not m_boGhost then begin
      //最高等级
      if (g_HighLevelHuman = nil) or (TPlayObject(g_HighLevelHuman).m_boGhost) then
        g_HighLevelHuman := Self
      else if m_Abil.level > TPlayObject(g_HighLevelHuman).m_Abil.level then
        g_HighLevelHuman := Self;
      //最高PK
      if (g_HighPKPointHuman = nil) or (TPlayObject(g_HighPKPointHuman).m_boGhost) then begin
        if m_nPkPoint > 0 then g_HighPKPointHuman := Self;
      end else if m_nPkPoint > TPlayObject(g_HighPKPointHuman).m_nPkPoint then
        g_HighPKPointHuman := Self;
      //最高攻击力
      if (g_HighDCHuman = nil) or (TPlayObject(g_HighDCHuman).m_boGhost)
        or (hiword(m_WAbil.DC) > hiword(TPlayObject(g_HighDCHuman).m_WAbil.DC)) then
        g_HighDCHuman := Self;
      //最高魔法
      if (g_HighMCHuman = nil) or (TPlayObject(g_HighMCHuman).m_boGhost)
        or (hiword(m_WAbil.MC) > HiWord(TPlayObject(g_HighMCHuman).m_WAbil.MC)) then
        g_HighMCHuman := Self;
      //最高道术
      if (g_HighSCHuman = nil) or (TPlayObject(g_HighSCHuman).m_boGhost)
        or (hiword(m_WAbil.SC) > HiWord(TPlayObject(g_HighSCHuman).m_WAbil.SC)) then
        g_HighSCHuman := Self;
      //最长在线时间
      if (g_HighOnlineHuman = nil) or (TPlayObject(g_HighOnlineHuman).m_boGhost)
        or (m_dwLogonTick < TPlayObject(g_HighOnlineHuman).m_dwLogonTick) then
        g_HighOnlineHuman := Self;
    end;
  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg3);
    end;
  end;

  try
    if ((g_Config.boReNewChangeColor and (m_btReLevel > 0)) or m_boColorName)
      and (NowTick - m_dwReColorTick > g_Config.dwReNewNameColorTime) then begin
      m_dwReColorTick := NowTick;
      Inc(m_btReColorIdx);
      if m_btReColorIdx > High(g_Config.ReNewNameColor) then
        m_btReColorIdx := 0;
      m_btNameColor := g_Config.ReNewNameColor[m_btReColorIdx];
      RefNameColor;
    end;

    //检测侦听私聊对像
    if (m_GetWhisperHuman <> nil) then begin
      if m_GetWhisperHuman.m_boDeath or (m_GetWhisperHuman.m_boGhost) then
        m_GetWhisperHuman := nil;
    end;

    ProcessSpiritSuite();
  except

  end;

  try                                                                                               //清除夫妻、师徒
    if NowTick - m_dwClearObjTick > 10000 then begin
      m_dwClearObjTick := NowTick;
      if (m_DearHuman <> nil) and (m_DearHuman.m_boDeath or
        m_DearHuman.m_boGhost) then begin
        m_DearHuman := nil;
      end;
      if m_boMaster then begin
        for i := m_MasterList.Count - 1 downto 0 do begin
          PlayObject := TPlayObject(m_MasterList.Items[i]);
          if (PlayObject <> nil) and (PlayObject.m_boDeath or PlayObject.m_boGhost) then begin
            m_MasterList.Delete(i);
          end;
        end;
      end else begin
        if (m_MasterHuman <> nil) and (m_MasterHuman.m_boDeath or
          m_MasterHuman.m_boGhost) then begin
          m_MasterHuman := nil;
        end;
      end;
      {减少心魔宝宝镇魔值}
      if (m_nEvilFollowerPower > 0) and (g_Config.nEvilCtrl10SecDecPower {3} > 0) then begin
        if m_nEvilFollowerPower > g_Config.nEvilCtrl10SecDecPower * 1000 then begin
          Dec(m_nEvilFollowerPower, g_Config.nEvilCtrl10SecDecPower * 1000);
          SendDefMessage(CM_RECALLEVIL, Integer(Self), 3,
            LoWord(m_nEvilFollowerPower), HiWord(m_nEvilFollowerPower), '');
          ClearEvilFollower(5);
          if (m_nEvilFollowerPower <= 1000 * 2) and (m_nEvilFollowerPower >= 1000) then begin
            ClearEvilFollower(1);
            SysMsg('你所操控的心魔即将背叛,请立刻使用镇魔符震慑', c_Red, t_Hint);
          end;
          if m_nEvilFollowerPower <= 1000 * 1 then begin
            ClearEvilFollower(2);
          end;
        end else begin
          m_nEvilFollowerPower := 0;
          ClearEvilFollower(3);
        end;
      end;
    end;
  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg4);
      MainOutMessage(E.Message);
    end;
  end;

  try
    if (m_nAutoGetExpPoint > 0) and ((m_AutoGetExpEnvir = nil) or
      (m_AutoGetExpEnvir = m_PEnvir)) and (NowTick - m_dwAutoGetExpTick > m_nAutoGetExpTime) then begin
      m_dwAutoGetExpTick := NowTick;
      if not m_boAutoGetExpInSafeZone or (m_boAutoGetExpInSafeZone and InSafeZone) then
        if m_boPneuma and (m_boPneumaEffMode) then
          //元神在灵珠状态不能获得经验
        else
          GetExp(m_nAutoGetExpPoint, 0, 0, False);
    end;
  except
    MainOutMessage(sExceptionMsg5);
  end;

  //延时脚本命令DelayCall的处理
  if m_DelayCall.Count > 0 then begin
    for i := m_DelayCall.Count - 1 downto 0 do begin
      DelayCall := pTDelayCall(m_DelayCall.Items[i]);
      if DelayCall.dwCallTime > 0 then begin
        if (NowTick >= DelayCall.dwCallTick) then begin
          DelayCall.dwCallTick := DelayCall.dwCallTick + DelayCall.dwDelayTime;
          Dec(DelayCall.dwCallTime);
          if DelayCall.dwCallTime = 0 then DelayCall.dwReleaseTick := NowTick;
          TmpNpc := UserEngine.FindMerchant(DelayCall.NPC);
          if TmpNpc = nil then
            TmpNpc := UserEngine.FindNPC(DelayCall.NPC);
          if TmpNpc <> nil then begin
            m_nScriptGotoCount := 0;
            TmpNpc.GotoLable(Self, DelayCall.sLabel, False);
          end;
          Break;
        end;
      end else begin
        if (DelayCall.dwReleaseTick > 0) and (GetTickCount - DelayCall.dwReleaseTick > 60 * 1000) then begin
          Dispose(pTDelayCall(m_DelayCall.Items[i]));
          m_DelayCall.Delete(i);
          Break;
        end;
      end;
    end;
  end;

  //延时脚本命令(一柱香)SetTimer的处理
  if (m_dwTimerLong > 0) then begin
    if (NowTick - m_dwTimerTick >= m_dwTimerLong * 1000) then begin
      m_dwTimerLong := 0;
      SendDefMessage(1833, 0, 0, 0, 0, '');
      if (m_sTimerLabel <> '') then
        ExecuteScript(g_ManageNPC, m_sTimerLabel);
    end;
  end;

  //延时脚本命令DelayGoto的处理
  if (m_dwDelayLong > 0) and (NowTick - m_dwDelayTick >= m_dwDelayLong) then begin
    m_dwDelayLong := 0;
    if (m_sTimeGotoLable <> '') then begin
      if (m_TimeDelayNpc <> nil) then try
        m_nScriptGotoCount := 0;
        TNormNpc(m_TimeDelayNpc).GotoLable(Self, m_sTimeGotoLable, False);
      finally

      end;
    end;
  end;

  //脱机泡点的人物执行任意走动
  //GetFrontPosition(nX, nY);
  if m_boOfflineGetGamePoint and (m_nautologintype=0) and (not m_boPneuma) and g_Config.boOfflineMove and (m_wShopItemCount = 0) and (GetTickCount - m_dwMoveTick > 3200) then begin
    if Random(8) > 0 then begin
      //获取安全内一个任意坐标

      if Random(6) = 0 then m_btDirection := Random(8);
      if GetFrontPosition(nX, nY) then begin
        if m_PEnvir.CanWalk(nX, nY, False) and InSafeZone(m_PEnvir, nX, nY) then begin              //可以移动,检查是否在安全区
          if Random(3) = 0 then
            Runto(m_btDirection, False)
          else
            WalkTo(m_btDirection, False);
        end else begin
          TurnTo(Random(8));
        end;
      end;
      { //随机喊话
      if (m_sAutoSayMsg <> '') and (Random(200) = 0) and (m_sAutoSayMsg[1] <> '@') then
        ProcessSayMsg(m_sAutoSayMsg, 1);
      }
    end;
    m_dwMoveTick := GetTickCount;
  end;
   if m_boOfflineGetGamePoint  and (m_nautologintype<>0) and (not m_boPneuma) and g_Config.boOfflineMove and (m_wShopItemCount = 0) {and (GetTickCount - m_dwMoveTick >100)} then begin
      if Think then begin
        inherited;
        Exit;
      end;
  //     MainOutMessage('不-: ' + inttostr(GetTickCount));
   if (m_TargetCret <> nil) then begin
    if getAInoa(m_TargetCret.m_sCharName) then  begin
     DelTargetCreat();
      //  MainOutMessage('不--攻击: ' + m_TargetCret.m_sCharName);
    end;
   end;
      if (m_TargetCret = nil) and  ((GetTickCount - m_dwSearchEnemyTick) > 2000) then begin
        m_dwSearchEnemyTick := GetTickCount();
        SearchTarget();
      end;

      if m_boWalkWaitLocked then begin
        if (GetTickCount - m_dwWalkWaitTick) > m_dwWalkWait then begin
          m_boWalkWaitLocked := False;
        end;
      end;





    m_dwMoveTick := GetTickCount;
  end;
  //恐惧
  if (m_wStatusTimeArr[STATE_FEAR] > 0) and (GetTickCount - m_dwMoveTick > 450) and (m_wShopItemCount = 0) and (not m_boCatapultAttackMode) then begin
    case Random(80) of                                                                              //变换方向
      0..10: GetBackPosition(nX, nY);
      20..30: GetLeftPosition(nX, nY);
      50..60: GetRightPosition(nX, nY);
    else
      GetFrontPosition(nX, nY);
    end;
    m_btDirection := GetNextDirection(m_nCurrX, m_nCurrY, nX, nY);
    if m_PEnvir.MoveToMovingObject(m_nCurrX, m_nCurrY, Self, nX, nY, False) > 0 then begin
      m_nCurrX := nX;
      m_nCurrY := nY;
      SendRefMsg(RM_RUSH, MakeWord(m_btDirection, 5), m_nCurrX, m_nCurrY, CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), '')
    end else
      m_btDirection := Random(8);
    m_dwMoveTick := GetTickCount;
  end;

  try
    MagFieryDragonRun();                                                                            //火龙附体
  except
    MainOutMessage('[Exception] TPlayObject::Run -> 战争旋风');
  end;
  inherited Run;
end;

//发送进入游戏公告





function TPlayObject.gotopoint(smapName: string;nx,ny:integer): Boolean;
var
nC:integer;
begin

     if not m_boWalkWaitLocked and (Integer(GetTickCount - m_dwWalkTick) > 600) then begin
        m_dwWalkTick := GetTickCount();
        Inc(m_nWalkCount);
        if m_nWalkCount > m_nWalkStep then begin
          m_nWalkCount := 0;
          m_boWalkWaitLocked := True;
          m_dwWalkWaitTick := GetTickCount();
        end;
       m_boMission:=true;
       m_nMissionX:= nx   ;
       m_nMissionY:=ny   ;
        if not m_boRunAwayMode then begin
          if not m_boNoAttackMode then begin
            if m_TargetCret <> nil then begin

              if actAttackTarget then begin
                inherited;
                Exit;
              end;

            end else begin
              m_nTargetX := -1;
              if m_boMission then begin
                m_nTargetX := m_nMissionX;
                m_nTargetY := m_nMissionY;
              end;
            end;
          end;


        end else begin
          if (m_dwRunAwayTime > 0) and ((GetTickCount - m_dwRunAwayStart) > m_dwRunAwayTime) then begin
            m_boRunAwayMode := False;
            m_dwRunAwayTime := 0;
          end;
        end;


        if (m_nTargetX <> -1) then begin
          if (m_TargetCret <> nil) then begin
            nC := abs(m_nCurrX - m_TargetCret.m_nCurrX) + abs(m_nCurrY - m_TargetCret.m_nCurrY);
            if not m_boCanRemoteHit or (nC < 4) or (nC > 7) then
              GotoTargetXY();
          end else
            GotoTargetXY();
        end else begin

          if (m_TargetCret = nil) and (m_Master = nil) then
            Wondering()
          else if (m_Master <> nil) and (m_Master.m_TargetCret <> nil) then
            SetTargetCreat(m_Master.m_TargetCret);                                                  //设置攻击目标为主人的攻击目标
        end;
      end;

    end;





function TPlayObject.GetBagItemCount(sItemName: string): Integer;
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nIndex                                : Integer;
begin
  Result := 0;
  if sItemName = '' then Exit;

  nIndex := UserEngine.GetStdItemIdx(sItemName);
  if nIndex > 0 then begin
    StdItem := UserEngine.GetStdItem(nIndex);
    if StdItem = nil then Exit;

    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := pTUserItem(m_ItemList.Items[i]);
      if UserItem = nil then Exit;
      if UserItem.wIndex = nIndex then begin
        if CheckSPCode(StdItem.Reserved, RE_ALLOWPILE) then begin
          Inc(Result, UserItem.Dura);
        end else begin
          Inc(Result, 1);
        end;
      end;
    end;
  end;
end;

function TPlayObject.Think(): Boolean;
var
  nOldX, nOldY                          : Integer;
  nIdx                                  : Integer;
  nX, nY                                : Integer;
  nAmuletAC                             : Integer;
  tCode                                 : Integer;
resourcestring
  sExceptionMsg                         = 'function TAIPlayer.Think:: => Code = %d';
begin
  Result := False;
  tCode := 0;
  if (GetTickCount - m_dwThinkTick) > 1 * 1000 then begin
    try
      tCode := 1;
      m_dwThinkTick := GetTickCount();
      if m_PEnvir.GetXYObjCount(m_nCurrX, m_nCurrY) >= 2 then m_boDupMode := True;

      {设置攻击目标}
      if (m_TargetCret = nil) and (m_LastHiter <> nil) and IsProperTarget(m_LastHiter) then
        SetTargetCreat(m_LastHiter);
      tCode := 2;
      {跟随主人攻击}

      tCode := 3;
      if not IsProperTarget(m_TargetCret) then m_TargetCret := nil;
      if m_boDupMode then begin
        nOldX := m_nCurrX;
        nOldY := m_nCurrY;
        WalkTo(Random(8), False);
        if (nOldX <> m_nCurrX) or (nOldY <> m_nCurrY) then begin
          m_boDupMode := False;
          Result := True;
          SendRefMsg(SM_204, 0, 0, 0, 0, '');
          Exit;
        end;
      end;
      {心魔逃跑、使用非攻击性技能}
      if m_boHolySeize then Exit;
      tCode := 4;
      {金刚护体}
      if not Result and (m_MagicSkills[61] <> nil) and (m_nHushenDura = 0) then
        Result := DoSpell(m_MagicSkills[61], m_nCurrX, m_nCurrY, Self);
      {护身真气}
      {if not Result and (m_MagicSkills[42] <> nil) and (m_nHushenDura = 0) then
        Result := DoSpell(m_MagicSkills[42], m_nCurrX, m_nCurrY, Self); }
      {魔法盾}
      if not Result and (m_MagicSkills[31] <> nil) and (m_wStatusTimeArr[STATE_BUBBLEDEFENCEUP] = 0) then
        Result := DoSpell(m_MagicSkills[31], m_nCurrX, m_nCurrY, Self);
      {风影盾}
      if not Result and (m_MagicSkills[70] <> nil) and (m_wStatusTimeArr[STATE_FENGYINGDUN] = 0) then
        Result := DoSpell(m_MagicSkills[70], m_nCurrX, m_nCurrY, Self);
      tCode := 5;
      {风火轮-攻击性技能}
      if not Result and (m_TargetCret <> nil) and (m_MagicSkills[50] <> nil) and (m_wStatusTimeArr[STATE_FENGHUOLUN] = 0) then
        Result := DoSpell(m_MagicSkills[50], m_nCurrX, m_nCurrY, Self);
      tCode := 6;
      {幽灵盾}
      if not Result and (m_MagicSkills[14] <> nil) then begin
        if (m_wStatusTimeArr[STATE_MAGDEFENCEUP] = 0) then
          Result := DoSpell(m_MagicSkills[14], m_nCurrX, m_nCurrY, Self)
        else if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_wStatusTimeArr[STATE_MAGDEFENCEUP] = 0) then
          Result := DoSpell(m_MagicSkills[14], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master);
      end;
      tCode := 7;
      {神圣战甲术}
      if not Result and (m_MagicSkills[15] <> nil) and (GetBagItemCount('道符')>0)  then begin
        if (m_wStatusTimeArr[STATE_DEFENCEUP] = 0) then
          Result := DoSpell(m_MagicSkills[15], m_nCurrX, m_nCurrY, Self)
        else if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_wStatusTimeArr[STATE_DEFENCEUP] = 0) then
          Result := DoSpell(m_MagicSkills[15], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master);
      end;
      tCode := 8;
      {解毒术}
      if not Result and (m_MagicSkills[65] <> nil) then begin
        if m_wStatusTimeArr[POISON_DECHEALTH] <> 0 then
          Result := DoSpell(m_MagicSkills[65], m_nCurrX, m_nCurrY, Self)
        else if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_wStatusTimeArr[POISON_DECHEALTH] <> 0) then
          Result := DoSpell(m_MagicSkills[65], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master);
      end;
      tCode := 9;
      {神光术}
      if not Result and (m_MagicSkills[64] <> nil) then begin
        if (m_wStatusTimeArr[POISON_LOCKSPELL] <> 0) or (m_wStatusTimeArr[POISON_STONE] <> 0) then
          Result := DoSpell(m_MagicSkills[64], m_nCurrX, m_nCurrY, Self)
        else if (m_Master <> nil) and not m_Master.m_boGhost and ((m_Master.m_wStatusTimeArr[POISON_LOCKSPELL] <> 0) or (m_Master.m_wStatusTimeArr[POISON_STONE] <> 0)) then
          Result := DoSpell(m_MagicSkills[64], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master);
      end;
      tCode := 10;

      {强化骷髅术}
      if not Result and (m_MagicSkills[SKILL_66] <> nil) and (m_SlaveList.Count < 2) then begin
        Result := DoSpell(m_MagicSkills[SKILL_66], m_nCurrX, m_nCurrY, Self);
      end;
      {召唤神兽}
      if not Result and (m_MagicSkills[SKILL_SINSU] <> nil) and (m_SlaveList.Count < 1) then begin
        Result := DoSpell(m_MagicSkills[SKILL_SINSU], m_nCurrX, m_nCurrY, Self);
      end;
      {骷髅召唤术}
      if not Result and (m_MagicSkills[SKILL_SKELLETON] <> nil) and (m_SlaveList.Count < 1) then begin
        Result := DoSpell(m_MagicSkills[SKILL_SKELLETON], m_nCurrX, m_nCurrY, Self);
      end;

      tCode := 11;
      {心魔逃跑}
      if not Result and (Random(g_Config.nEvilEsCapeRate {10}) = 0) and
        (m_LastHiter <> nil) and (m_WAbil.dwHP / m_WAbil.dwMaxHP < Round(g_Config.nEvilEsCapeHP / 100)) and (GetTickCount - dwLastEscapeTick > 5000) then begin
        if (abs(m_nCurrX - m_LastHiter.m_nCurrX) <= 2) and (abs(m_nCurrY - m_LastHiter.m_nCurrY) <= 2) then begin
          if m_Master <> nil then
            m_Master.GetRightPosition(nX, nY)
          else begin
            nX := m_nCurrX + Random(g_Config.nEvilEsCapeRange {30}) + Random(3);
            nY := m_nCurrY + Random(g_Config.nEvilEsCapeRange {30}) + Random(3);
            if m_PEnvir.CanWalk(nX, nY, False) then begin
              SpaceMove(m_PEnvir.m_sMapName, nX, nY, 0, nil);
            end;
            if Result then begin
              DelTargetCreat;
              m_LastHiter := nil;
              dwLastEscapeTick := GetTickCount;                                                     //防止连续逃跑导致显示错误
            end;
          end;
          if Result and (g_Config.nEvilEsCapeHP / 100 > m_WAbil.dwHP / m_WAbil.dwMaxHP) then begin  //逃跑后,血量恢复百分比
            m_WAbil.dwHP := Round(m_WAbil.dwMaxHP * g_Config.nEvilEsCapeHP / 100);
            HealthSpellChanged;
          end;
        end;
      end;

      if not Result and (m_TargetCret = nil) then begin                                             //非攻击状态自动使用技能加血
        if GetTickCount - m_dwMagicAttackTick > m_dwMagicAttackInterval then begin
          {群体治疗术}
          if (m_MagicSkills[29] <> nil) and (m_btJob = 2) then begin
            if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_WAbil.dwHP / m_Master.m_WAbil.dwMaxHP < 0.95) then begin
              if DoSpell(m_MagicSkills[29], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master) then begin
                Result := True;
              end;
            end else if (m_WAbil.dwHP / m_WAbil.dwMaxHP < 0.95) then begin
              if DoSpell(m_MagicSkills[29], m_nCurrX, m_nCurrY, nil) then begin
                Result := True;
              end;
            end;
          end;
          {治疗术}
          if not Result and (m_MagicSkills[2] <> nil) and (m_btJob = 2) then begin
            if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_WAbil.dwHP / m_Master.m_WAbil.dwMaxHP < 0.95) then begin
              if DoSpell(m_MagicSkills[2], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master) then begin
                Result := True;
              end;
            end else if (m_WAbil.dwHP / m_WAbil.dwMaxHP < 0.95) then begin
              if DoSpell(m_MagicSkills[2], m_nCurrX, m_nCurrY, nil) then begin
                Result := True;
              end;
            end;
          end;
        end;
      end;
      if Result then begin
        m_dwMagicAttackTick := GetTickCount;
        m_dwHitTick := GetTickCount();
        m_boCanRemoteHit := True;
      end;
    except
      on E: Exception do begin
        MainOutMessage(Format(sExceptionMsg, [tCode]));
        MainOutMessage(E.Message);
      end;
    end;
  end;
end;



procedure TPlayObject.SetTargetXY(nX, nY: Integer);
begin
  m_nTargetX := nX;
  m_nTargetY := nY;
end;
//获得魔法的Spell

function TPlayObject.GetMagicSpell(UserMagic: pTUserMagic): Integer;
begin
  Result := Round(UserMagic.MagicInfo.wSpell / (UserMagic.MagicInfo.btTrainLv + 1) * (UserMagic.btLevel + 1)) + UserMagic.MagicInfo.btDefSpell;
end;
//物理攻击

procedure TPlayObject.Attack(TargeTBaseObject: TBaseObject; nDir: Integer);

  function IsEnoughMP(UserMagic: pTUserMagic): Boolean;
  begin
    if g_Config.boEvilNotDecMP then
      Result := True
    else
      Result := m_WAbil.dwMP >= UserMagic.MagicInfo.btDefSpell + GetMagicSpell(UserMagic);
  end;
var
  wIdent                                : Word;
  nMagicID                              : Integer;
  pMagic                                : pTUserMagic;
begin
  {找一个攻击模式}
  wIdent := 0;
  nMagicID := 0;
  pMagic := nil;
  m_btDirection := nDir;
  if TargeTBaseObject <> nil then begin
    if (GetPoseCreate = TargeTBaseObject) then begin
      if (Random(5) = 0) then begin
        {狮子吼}
        if (m_MagicSkills[37] <> nil) and IsEnoughMP(m_MagicSkills[37]) then begin
          pMagic := m_MagicSkills[37];
          DoSpell(pMagic, m_nCurrX, m_nCurrY, TargeTBaseObject);
          Exit;
        end
        {突斩}
        else if (m_MagicSkills[62] <> nil) and IsEnoughMP(m_MagicSkills[62]) then
          pMagic := m_MagicSkills[62]
        {野蛮}
        else if (m_MagicSkills[27] <> nil) and IsEnoughMP(m_MagicSkills[27]) then
          pMagic := m_MagicSkills[27];
        {野蛮、突斩}
        if pMagic <> nil then begin
          if (GetTickCount - m_dwDoMotaeboTick) > 3 * 1000 then begin
            m_dwDoMotaeboTick := GetTickCount();
            DamageSpell(GetSpellPoint(pMagic));
            // HealthSpellChanged();                                            //心魔不需要发送MP消息
            DoMotaebo(m_btDirection, pMagic.btLevel, pMagic.GetMagIdx);
          end;
          Exit;
        end;
      end;

      if (pMagic = nil) then begin
        nDir := m_btDirection;
        if (m_MagicSkills[60] <> nil) and IsEnoughMP(m_MagicSkills[60]) then                        //破盾
          AttackDir(nil, 13, nDir)
        else if (m_MagicSkills[59] <> nil) and IsEnoughMP(m_MagicSkills[59]) then                   //破击
          AttackDir(nil, 12, nDir)
        else if (m_MagicSkills[SKILL_88] <> nil) and IsEnoughMP(m_MagicSkills[SKILL_88]) then       //强化攻杀剑法
          AttackDir(nil, 18, nDir)
        else if (m_MagicSkills[44] <> nil) and IsEnoughMP(m_MagicSkills[44]) then                   //雷霆剑
          AttackDir(nil, 15, nDir)
        else if (m_MagicSkills[43] <> nil) and IsEnoughMP(m_MagicSkills[43]) then                   //抱月刀
          AttackDir(nil, 14, nDir)
        else if (m_MagicSkills[41] <> nil) and (Random(8) < m_MagicSkills[41].btLevel + 1) then     //血影刀法
          AttackDir(nil, 17, nDir)
        else if (m_MagicSkills[40] <> nil) and (Random(8) < m_MagicSkills[40].btLevel + 1) then     //残影刀法
          AttackDir(nil, 16, nDir)
        else if (m_MagicSkills[26] <> nil) and (Random(10) < m_MagicSkills[26].btLevel + 1) then    //烈火剑法
          AttackDir(nil, 7, nDir)
        else if (m_MagicSkills[25] <> nil) and (Random(8) < m_MagicSkills[25].btLevel + 1) then     //半月弯刀
          AttackDir(nil, 5, nDir)
        else if (m_MagicSkills[12] <> nil) and (Random(10) < m_MagicSkills[12].btLevel + 1) then    //刺杀剑术
          AttackDir(nil, 4, nDir)
        else if (m_MagicSkills[7] <> nil) and (Random(10) < m_MagicSkills[7].btLevel + 1) then      //攻杀剑法
          AttackDir(nil, 3, nDir)
        else
          AttackDir(nil, Random(3), nDir);                                                          //普通攻击

        if (m_MagicSkills[7] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
          Dec(m_btAttackSkillCount);
          if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
            m_boPowerHit := True;
          end;
          if m_btAttackSkillCount <= 0 then begin
            m_btAttackSkillCount := 7 - m_MagicSkills[7].btLevel;
            m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
          end;
        end else if (m_MagicSkills[40] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
          Dec(m_btAttackSkillCount);
          if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
            m_boPowerHit := True;
          end;
          if m_btAttackSkillCount <= 0 then begin
            m_btAttackSkillCount := 7 - m_MagicSkills[40].btLevel;
            m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
          end;
        end else if (m_MagicSkills[41] <> nil) and (m_UseItems[U_WEAPON].Dura > 0) then begin
          Dec(m_btAttackSkillCount);
          if m_btAttackSkillPointCount = m_btAttackSkillCount then begin
            m_boPowerHit := True;
          end;
          if m_btAttackSkillCount <= 0 then begin
            m_btAttackSkillCount := 7 - m_MagicSkills[41].btLevel;
            m_btAttackSkillPointCount := Random(m_btAttackSkillCount);
          end;
        end;
        Dec(m_nHealthTick, 30);
        Dec(m_nSpellTick, 100);
        m_nSpellTick := _MAX(0, m_nSpellTick);
        Dec(m_nPerHealth, 2);
        Dec(m_nPerSpell, 2);
      end;
      m_dwHitTick := GetTickCount();
    end;
  end;
end;

function TPlayObject.actAttackTarget(): Boolean;
var
  bt06, nCount                          : Byte;
begin
  Result := False;
  if m_TargetCret = nil then Exit;
  if m_boHolySeize then Exit;
  {检查有没有HP恢复的技能,若有且可以使用,则使用该技能}
  if GetTickCount - m_dwMagicAttackTick > m_dwMagicAttackInterval then begin
    if (m_MagicSkills[2] <> nil) and (m_btJob = 2) then begin
      if (m_Master <> nil) and not m_Master.m_boGhost and (m_Master.m_WAbil.dwHP / m_Master.m_WAbil.dwMaxHP < 0.5) then begin
        if DoSpell(m_MagicSkills[2], m_Master.m_nCurrX, m_Master.m_nCurrY, m_Master) then begin
          Result := True;
        end;
      end else if (m_WAbil.dwHP / m_WAbil.dwMaxHP < 0.5) then begin
        if DoSpell(m_MagicSkills[2], m_nCurrX, m_nCurrY, nil) then begin
          Result := True;
        end;
      end;
    end;
  //  MainOutMessage('物品名字重复: ' + m_TargetCret.m_sCharName);
    {检查在是否在攻击范围内,使用远程攻击的技能}
    if not Result and (abs(m_nCurrX - m_TargetCret.m_nCurrX) < 8) and (abs(m_nCurrY - m_TargetCret.m_nCurrY) < 8) then begin

      {强化施毒术}
      if not Result and (m_MagicSkills[89] <> nil) and ((m_TargetCret.m_wStatusTimeArr[POISON_DECHEALTH] = 0) or (m_TargetCret.m_wStatusTimeArr[POISON_DAMAGEARMOR] = 0)) then
        Result := DoSpell(m_MagicSkills[89], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {施毒术}
      if not Result and (m_MagicSkills[SKILL_AMYOUNSUL] <> nil) and ((m_TargetCret.m_wStatusTimeArr[POISON_DECHEALTH] = 0) or (m_TargetCret.m_wStatusTimeArr[POISON_DAMAGEARMOR] = 0)) then
        Result := DoSpell(m_MagicSkills[SKILL_AMYOUNSUL], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);

      {强化诅咒术}
      if not Result and (m_MagicSkills[SKILL_90] <> nil) and (Random(12) = 0) and ((m_TargetCret.m_wStatusTimeArr[POISON_DECDEFENCE] = 0) or (m_TargetCret.m_wStatusTimeArr[POISON_DECMANA] = 0)) then
        Result := DoSpell(m_MagicSkills[SKILL_90], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {诅咒术}
      if not Result and (m_MagicSkills[SKILL_45] <> nil) and (Random(12) = 0) and ((m_TargetCret.m_wStatusTimeArr[POISON_DECDEFENCE] = 0) or (m_TargetCret.m_wStatusTimeArr[POISON_DECMANA] = 0)) then
        Result := DoSpell(m_MagicSkills[SKILL_45], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {狂龙紫电}
      if not Result and (m_MagicSkills[71] <> nil)  and ((GetTickCount -  m_MagicSkills[71].dwSkillTimeTick)>900)  then    begin
        Result := DoSpell(m_MagicSkills[71], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
         m_MagicSkills[71].dwSkillTimeTick:=GetTickCount;
      end;
      {流星火雨}
      if not Result and (m_MagicSkills[73] <> nil) then
        Result := DoSpell(m_MagicSkills[73], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {雷电术}
      if not Result and (m_MagicSkills[SKILL_LIGHTENING] <> nil) and ((GetTickCount -  m_MagicSkills[SKILL_LIGHTENING].dwSkillTimeTick)>m_MagicSkills[SKILL_LIGHTENING].MagicInfo.dwDelayTime) then begin
        Result := DoSpell(m_MagicSkills[SKILL_LIGHTENING], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
        m_MagicSkills[SKILL_LIGHTENING].dwSkillTimeTick:=GetTickCount;
      end;
      {幽冥火咒}
      if not Result and (m_MagicSkills[67] <> nil) and ((GetTickCount -  m_MagicSkills[67].dwSkillTimeTick)>m_MagicSkills[67].MagicInfo.dwDelayTime) then  begin
        Result := DoSpell(m_MagicSkills[67], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
        m_MagicSkills[67].dwSkillTimeTick:=GetTickCount;
      end;
      {灵魂火符}
      if not Result and (m_MagicSkills[13] <> nil) and ((GetTickCount -  m_MagicSkills[13].dwSkillTimeTick)>m_MagicSkills[13].MagicInfo.dwDelayTime)  then   begin
        Result := DoSpell(m_MagicSkills[13], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
        m_MagicSkills[13].dwSkillTimeTick:=GetTickCount;
      end;
      {冰旋风}
      if not Result and (m_MagicSkills[54] <> nil) then
        Result := DoSpell(m_MagicSkills[54], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {五雷轰}
      if not Result and (m_MagicSkills[53] <> nil) then
        Result := DoSpell(m_MagicSkills[53], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {冰龙破}
      if not Result and (m_MagicSkills[51] <> nil) then
        Result := DoSpell(m_MagicSkills[51], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {冰箭术}
      if not Result and (m_MagicSkills[49] <> nil) then
        Result := DoSpell(m_MagicSkills[49], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {冰咆哮}
      if not Result and (m_MagicSkills[33] <> nil) then
        Result := DoSpell(m_MagicSkills[33], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {地狱雷光}
      if not Result and (m_MagicSkills[24] <> nil) then
        Result := DoSpell(m_MagicSkills[24], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {爆裂火焰}
      if not Result and (m_MagicSkills[23] <> nil) then
        Result := DoSpell(m_MagicSkills[23], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {火墙}
      if not Result and (m_MagicSkills[22] <> nil) then
        Result := DoSpell(m_MagicSkills[22], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {强化火球}
      if not Result and (m_MagicSkills[87] <> nil) then
        Result := DoSpell(m_MagicSkills[87], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
      {小火球}
      if not Result and (m_MagicSkills[1] <> nil) then
        Result := DoSpell(m_MagicSkills[1], m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
    end;
  end;

   //如果可以使用远程攻击
  if Result then begin
//    MainOutMessage('自动躲避: 1' );
    m_boCanRemoteHit := True;
    m_dwMagicAttackTick := GetTickCount;
    m_dwHitTick := GetTickCount();
    if m_Master <> nil then begin                                                                   //重新设置目标坐标
      m_nTargetX := -1;
    end;
//    Exit;
  end else  begin
    m_boCanRemoteHit := False;
  //  MainOutMessage('自动躲避: 2' );
  end;
  //法师不近身攻击
//   MainOutMessage('自动躲避: '+inttostr(abs(m_nCurrX - m_TargetCret.m_nCurrX))+ inttostr(abs(m_nCurrY - m_TargetCret.m_nCurrY)));
  if (m_TargetCret <> nil) and
    ((m_btJob = 1) or (m_btJob = 2))  and
    (abs(m_nCurrX - m_TargetCret.m_nCurrX) < 4) and (abs(m_nCurrY - m_TargetCret.m_nCurrY) < 4) then
  begin
    AutoAvoid();                                                                                    //自动躲避
    if (m_TargetCret.m_PEnvir <> m_PEnvir) then DelTargetCreat();
    Exit;
  end;

  if not Result and GetAttackDir(m_TargetCret, bt06) then begin                                     //物理攻击
    if (GetTickCount - m_dwHitTick) > m_nNextHitTime then begin
      m_dwHitTick := GetTickCount();
      m_dwTargetFocusTick := GetTickCount();
      m_dwMagicAttackTick := GetTickCount;
      if not Result then
        Attack(m_TargetCret, bt06);
      BreakHolySeizeMode();
    end;
    Result := True;
  end else begin
    if (m_TargetCret.m_PEnvir = m_PEnvir) then begin                                                //法师远程攻击
      SetTargetXY(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
    end else begin
      DelTargetCreat();
    end;
  end;
end;

{行走到目标}

procedure TPlayObject.GotoTargetXY;
var
  i                                     : Integer;
  nDir                                  : Integer;
  n10                                   : Integer;
  n14                                   : Integer;
  n20                                   : Integer;
  nOldX                                 : Integer;
  nOldY                                 : Integer;
  nX, nY                                : Integer;
  boRun                                 : Boolean;
begin
  boRun := False;

   MainOutMessage('走到目标: '+inttostr(m_nCurrY)+'-    '+inttostr(m_nTargetY) );
  if ((m_nCurrX <> m_nTargetX) or (m_nCurrY <> m_nTargetY)) then begin
    n10 := m_nTargetX;
    n14 := m_nTargetY;
    dwTick3F4 := GetTickCount();
    nDir := DR_DOWN;
    if n10 > m_nCurrX then begin
      nDir := DR_RIGHT;
      if n14 > m_nCurrY then nDir := DR_DOWNRIGHT;
      if n14 < m_nCurrY then nDir := DR_UPRIGHT;
    end else begin
      if n10 < m_nCurrX then begin
        nDir := DR_LEFT;
        if n14 > m_nCurrY then nDir := DR_DOWNLEFT;
        if n14 < m_nCurrY then nDir := DR_UPLEFT;
      end else begin
        if n14 > m_nCurrY then nDir := DR_DOWN
        else if n14 < m_nCurrY then nDir := DR_UP;
      end;
    end;
    nOldX := m_nCurrX;
    nOldY := m_nCurrY;

    if (abs(m_nCurrX - m_nTargetX) > 3) or (abs(m_nCurrY - m_nTargetY) > 3) then begin
      if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, nDir, 2, nX, nY) then boRun := True;
    end;
    if boRun then boRun := runto(nDir, False);
    if not boRun then WalkTo(nDir, False);
    n20 := Random(3);
    for i := DR_UP to DR_UPLEFT do begin
      if (nOldX = m_nCurrX) and (nOldY = m_nCurrY) then begin
        if n20 <> 0 then Inc(nDir)
        else if nDir > 0 then Dec(nDir)
        else nDir := DR_UPLEFT;
        if (nDir > DR_UPLEFT) then nDir := DR_UP;
        WalkTo(nDir, False);
      end;
    end;

    if ((nOldX = m_nCurrX) and (nOldY = m_nCurrY)) then begin
      if m_boWalking then begin
        SendRefMsg(SM_204, 0, 0, 0, 0, '');
        m_boWalking := False;
      end;
    end else
      m_boWalking := True;
  end else begin
    m_nTargetX := -1;
    if m_boWalking then begin
      SendRefMsg(SM_204, 0, 0, 0, 0, '');
      m_boWalking := False;
    end;
  end;
end;

{检测指定方向和范围内坐标的怪物数量}

function TPlayObject.CheckTargetXYCount(nX, nY, nRange: Integer): Integer;
var
  BaseObject                            : TBaseObject;
  i, nC, n10                            : Integer;
begin
  Result := 0;
  n10 := nRange;
  for i := 0 to m_VisibleActors.Count - 1 do begin
    BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
    if BaseObject <> nil then begin
      if not BaseObject.m_boDeath then begin
        if IsProperTarget(BaseObject) then begin
          if ((BaseObject.m_boHideMode = False) or (m_boCoolEye = True)) and (BaseObject.m_boHideModeEx = False) then begin
            nC := abs(nX - BaseObject.m_nCurrX) + abs(nY - BaseObject.m_nCurrY);
            if nC <= n10 then begin
              Inc(Result);
              if Result > 2 then Break;
            end;
          end;
        end;
      end;
    end;
  end;
end;

function TPlayObject.CheckTargetXYCountOfDirection(nX, nY, nDir, nRange: Integer): Integer;
var
  BaseObject                            : TBaseObject;
  i, nC, n10                            : Integer;
begin
  Result := 0;
  n10 := 2;
  for i := 0 to m_VisibleActors.Count - 1 do begin
    BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
    if BaseObject <> nil then begin
      if not BaseObject.m_boDeath then begin
        if IsProperTarget(BaseObject) and (not BaseObject.m_boHideMode) then begin
          case nDir of
            DR_UP: begin
                if (abs(nX - BaseObject.m_nCurrX) <= nRange) and ((BaseObject.m_nCurrY - nY) in [0, nRange]) then Inc(Result);
              end;
            DR_UPRIGHT: begin
                if ((BaseObject.m_nCurrX - nX) in [0, nRange]) and ((BaseObject.m_nCurrY - nY) in [0, nRange]) then Inc(Result);
              end;
            DR_RIGHT: begin
                if ((BaseObject.m_nCurrX - nX) in [0, nRange]) and (abs(nY - BaseObject.m_nCurrY) <= nRange) then Inc(Result);
              end;
            DR_DOWNRIGHT: begin
                if ((BaseObject.m_nCurrX - nX) in [0, nRange]) and ((nY - BaseObject.m_nCurrY) in [0, nRange]) then Inc(Result);
              end;
            DR_DOWN: begin
                if (abs(nX - BaseObject.m_nCurrX) <= nRange) and ((nY - BaseObject.m_nCurrY) in [0, nRange]) then Inc(Result);
              end;
            DR_DOWNLEFT: begin
                if ((nX - BaseObject.m_nCurrX) in [0, nRange]) and ((nY - BaseObject.m_nCurrY) in [0, nRange]) then Inc(Result);
              end;
            DR_LEFT: begin
                if ((nX - BaseObject.m_nCurrX) in [0, nRange]) and (abs(nY - BaseObject.m_nCurrY) <= nRange) then Inc(Result);
              end;
            DR_UPLEFT: begin
                if ((nX - BaseObject.m_nCurrX) in [0, nRange]) and ((BaseObject.m_nCurrY - nY) in [0, nRange]) then Inc(Result);
              end;
          end;
          if Result > 2 then Break;
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.GotoTargetXYRange();
var
  n10                                   : Integer;
  n14                                   : Integer;
begin
  if CheckTargetXYCount(m_nCurrX, m_nCurrY, 10) < 1 then begin
    n10 := abs(m_TargetCret.m_nCurrX - m_nCurrX);
    n14 := abs(m_TargetCret.m_nCurrY - m_nCurrY);
    if n10 > 4 then Dec(n10, 5) else n10 := 0;
    if n14 > 4 then Dec(n14, 5) else n14 := 0;
    if m_TargetCret.m_nCurrX > m_nCurrX then m_nTargetX := m_nCurrX + n10;
    if m_TargetCret.m_nCurrX < m_nCurrX then m_nTargetX := m_nCurrX - n10;
    if m_TargetCret.m_nCurrY > m_nCurrY then m_nTargetY := m_nCurrY + n14;
    if m_TargetCret.m_nCurrY < m_nCurrY then m_nTargetY := m_nCurrY - n14;

    m_boRunAwayMode := True;
    m_dwRunAwayStart := GetTickCount();
    m_dwRunAwayTime := 2 * 1000;
//    GotoTargetXY();
  end;
end;

{自动躲避}

function TPlayObject.AutoAvoid(): Boolean;

  function GetAvoidDir(): Integer;
  var
    n10                                 : Integer;
    n14                                 : Integer;
  begin
    n10 := m_TargetCret.m_nCurrX;
    n14 := m_TargetCret.m_nCurrY;
    Result := DR_DOWN;
    if n10 > m_nCurrX then begin
      Result := DR_LEFT;
      if (n14 > m_nCurrY) then
        Result := DR_DOWNLEFT
      else if Random(5) = 0 then
        Result := DR_UPLEFT;
    end else begin
      if n10 < m_nCurrX then begin
        Result := DR_RIGHT;
        if n14 > m_nCurrY then Result := DR_DOWNRIGHT
        else if Random(5) = 0 then Result := DR_UPRIGHT;
        //if n14 < m_nCurrY then Result := DR_UPRIGHT;
      end else begin
        if n14 > m_nCurrY then Result := DR_UP
        else
          if n14 < m_nCurrY then Result := DR_DOWN;
      end;
    end;
  end;

  function SearchNextDir(var nTargetX, nTargetY: Integer): Boolean;
  var
    i                                   : Integer;
    nDir                                : Integer;
    n01                                 : Integer;
    n02                                 : Integer;
    n03                                 : Integer;
    n04                                 : Integer;
    n05                                 : Integer;
    n06                                 : Integer;
    n07                                 : Integer;
    n08                                 : Integer;
    n10                                 : Integer;
    boGotoL2                            : Boolean;
  label
    L001;
  label
    L002;
  label
    L003;
  begin
    Result := False;
    if not Result then begin
      nDir := GetAvoidDir;
      boGotoL2 := False;
      goto L001;
    end;

    L002:
    if not Result then begin
      n10 := 0;
      while True do begin
        Inc(n10);
        nDir := Random(8);
        if nDir in [0..7] then Break;
        if n10 > 8 then Break;
      end;
      goto L001;
    end;

    L001:
    n01 := 0;
    n02 := 0;
    n03 := 0;
    n04 := 0;
    n05 := 0;
    n06 := 0;
    n07 := 0;
    n08 := 0;
    while True do begin
      if nDir > DR_UPLEFT then Break;
      case nDir of
        DR_UP: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Inc(nTargetY, 10 - n01);
              Result := True;
              Break;
            end else begin
              if n01 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Inc(nTargetY);
              Inc(n01);
              Continue;
            end;
          end;
        DR_UPRIGHT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Inc(nTargetX, 10 - n02);
              Inc(nTargetY, 10 - n02);
              Result := True;
              Break;
            end else begin
              if n02 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Inc(nTargetX);
              Inc(nTargetY);
              Inc(n02);
              Continue;
            end;
          end;
        DR_RIGHT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Inc(nTargetX, 10 - n03);
              Result := True;
              Break;
            end else begin
              if n03 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Inc(nTargetX);
              Inc(n03);
              Continue;
            end;
          end;
        DR_DOWNRIGHT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Inc(nTargetX, 10 - n04);
              Dec(nTargetY, 10 - n04);
              Result := True;
              Break;
            end else begin
              if n04 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Inc(nTargetX);
              Dec(nTargetY);
              Inc(n04);
              Continue;
            end;
          end;
        DR_DOWN: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Dec(nTargetY, 10 - n05);
              Result := True;
              Break;
            end else begin
              if n05 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Dec(nTargetY);
              Inc(n05);
              Continue;
            end;
          end;
        DR_DOWNLEFT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Dec(nTargetX, 10 - n06);
              Dec(nTargetY, 10 - n06);
              Result := True;
              Break;
            end else begin
              if n06 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Dec(nTargetX);
              Dec(nTargetY);
              Inc(n06);
              Continue;
            end;
          end;
        DR_LEFT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Dec(nTargetX, 10 - n07);
              Result := True;
              Break;
            end else begin
              if n07 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Dec(nTargetX);
              Inc(n07);
              Continue;
            end;
          end;
        DR_UPLEFT: begin
            if m_PEnvir.CanWalkEx(nTargetX, nTargetY, True) and (CheckTargetXYCountOfDirection(nTargetX, nTargetY, nDir, 5) = 0) then begin
              Dec(nTargetX, 10 - n08);
              Inc(nTargetY, 10 - n08);
              Result := True;
              Break;
            end else begin
              if n08 >= 10 then begin
                nTargetX := m_nCurrX;
                nTargetY := m_nCurrY;
                Inc(nDir);
                Continue;
              end;
              Dec(nTargetX);
              Inc(nTargetY);
              Inc(n08);
              Continue;
            end;
          end;
      end;
    end;
    if (not boGotoL2) and (not Result) then begin
      boGotoL2 := True;
      goto L002;
    end;
  end;
var
  n10                                   : Integer;
  n14                                   : Integer;
  n20                                   : Integer;
  nOldX                                 : Integer;
  nOldY                                 : Integer;
  n16                                   : Integer;
  nLoopCount                            : Integer;
begin
  if not m_boCanRemoteHit then Exit;
     MainOutMessage('自动躲避: ' );
  if (GetTickCount - m_dwAutoAvoidTick > 3 * 1000) then begin
    m_dwAutoAvoidTick := GetTickCount();
    if m_TargetCret <> nil then begin
      n10 := 0;
      if CheckTargetXYCount(m_nCurrX, m_nCurrY, 5) > 0 then begin
        while True do begin
          Inc(n10);
          m_nTargetX := m_nCurrX;
          m_nTargetY := m_nCurrY;
          if SearchNextDir(m_nTargetX, m_nTargetY) then begin
            m_boRunAwayMode := True;
            m_dwRunAwayStart := GetTickCount();
            m_dwRunAwayTime := 2 * 1000;
          end;
            //GotoTargetXY();
          if CheckTargetXYCount(m_nCurrX, m_nCurrY, 5) = 0 then Break;
          if n10 >= 1 then Break;
        end;
      end;
      GotoTargetXYRange();
    end;
  end;
end;

{无行为目标}

procedure TPlayObject.UpdatenoatcktActors(BaseObject: TBaseObject);                                    //004B939C
var
  I                                     : Integer;
  boIsVisible                           : Boolean;
  VisibleBaseObject                     : pTVisibleBaseObject;
begin
  boIsVisible := False;
// if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) or (BaseObject.m_Master <> nil) then
//    m_boIsVisibleActive:=True;//如果是人物或宝宝则置TRUE
  for I := 0 to m_noatcktActors.Count - 1 do
  begin
    VisibleBaseObject := m_noatcktActors.Items[I];
    if VisibleBaseObject.BaseObject = BaseObject then
    begin
      VisibleBaseObject.nVisibleFlag := 1;
      boIsVisible := True;
      break;
    end;
  end;
  if boIsVisible then
    exit;
  New(VisibleBaseObject);
  VisibleBaseObject.nVisibleFlag := 2;
  VisibleBaseObject.BaseObject := BaseObject;
  m_noatcktActors.Add(VisibleBaseObject);
end;

function TPlayObject.canatackTarget(BaseObject:TBaseObject): Boolean;


var
  I                                     : Integer;
  noatackBaseObject                     : pTVisibleBaseObject;
begin
   Result := true;
  for I := 0 to m_noatcktActors.Count - 1 do
  begin
    noatackBaseObject := m_noatcktActors.Items[I];
    if (TBaseObject(noatackBaseObject.BaseObject)=BaseObject) then
    begin
      Result := false;
      break;
    end;
  end;
end;

procedure TPlayObject.Wondering();

var
  nX, nY,ncode,nDir,bx,by: Integer;

begin
m_boAIStart:=true;
m_nround:=20;
  if m_boAIStart and
    (m_TargetCret = nil) and
    (not m_boGhost) and
    (not m_boDeath) and
    (not m_boFixedHideMode) and
    (not m_boStoneMode) and
    (m_wStatusTimeArr[POISON_STONE] = 0) then begin
   try


   MainOutMessage(Format('%s往回走:(%d / %d)', [m_sCharName,start_x, start_y]));


    if (abs(m_nCurrX - start_x) + abs(m_nCurry - start_y) >m_nround) then  begin

    if  m_nMoveFailCount> 10 then   begin
      MapRandomMove(m_PEnvir.m_sMapName, 0,nil);
      m_nMoveFailCount:=0;
    end;

    bx:=  start_x+4-random(8) ;
     by:=  start_y+4-random(8) ;
            nDir := GetNextDirection(m_nCurrX, m_nCurrY, bx, by);
            m_PEnvir.GetNextPosition(start_x, start_y, nDir, 2, m_nTargetX, m_nTargetY);

              if not runto(nDir, false) then  GotoTargetXY();
              Inc(m_nMoveFailCount);
             //    MainOutMessage(Format('%s往回:(%d / %d/ %d)', [m_sCharName,start_x, start_y,m_nround]));
        exit;
    //  MainOutMessage(Format('%s往回走:(%d / %d)', [m_sCharName,start_x, start_y]));
    end;

    //if not m_PointManager.Finish then begin
    nX := m_nCurrX;
    nY := m_nCurrY;
    //  MainOutMessage(Format('TAIObject.Wondering0:(%d / %d)', [nX, nY]));
      //m_PointManager.SetThroughPoint(m_nCurrX, m_nCurrY);
    if (Length(m_Path) > 0) and (m_nPostion < Length(m_Path)) then begin
      if not GotoNextOne(m_Path[m_nPostion].X, m_Path[m_nPostion].Y, True) then begin
        m_Path := nil;
        m_nPostion := -1;
        Inc(m_nMoveFailCount);
        Inc(m_nPostion);
      end else begin
        m_nMoveFailCount := 0;
        //MainOutMessage(m_sCharName + ' GotoNextOne FindPath:' + IntToStr(Length(m_Path)));
        Exit;
      end;
    end else begin
      m_Path := nil;
      m_nPostion := -1;
    end;
    ncode:=0;
    if m_PointManager.GetPoint(nX, nY) then begin
      if (abs(nX - m_nCurrX) > 2) or (abs(nY - m_nCurrY) > 2) then begin
        g_FindPath.BaseObject := Self;
        m_Path := g_FindPath.FindPath(m_PEnvir, m_nCurrX, m_nCurrY, nX, nY, True, False);
        m_nPostion := 0;
        ncode:=2;
        //MainOutMessage(m_sCharName + ' FindPath:' + IntToStr(Length(m_Path)));
        if (Length(m_Path) > 0) and (m_nPostion < Length(m_Path)) then begin
          if not GotoNextOne(m_Path[m_nPostion].X, m_Path[m_nPostion].Y, True) then begin
            m_Path := nil;
            m_nPostion := -1;
            Inc(m_nMoveFailCount);
          end else begin
            m_nMoveFailCount := 0;
            Inc(m_nPostion);
            Exit;
          end;
       ncode:=3;
        end else begin
          m_Path := nil;
          m_nPostion := -1;
          Inc(m_nMoveFailCount);
        end;
      end else begin
        if GotoNextOne(nX, nY, True) then begin
          m_nMoveFailCount := 0;
        end else begin
          Inc(m_nMoveFailCount);
        end;
      end;
      //MainOutMessage(Format('%s TAIObject.Wondering1:(%d / %d)', [m_sCharName, nX, nY]));
        //if GotoNextOne(nX, nY, True) then MainOutMessage(Format('%s TAIObject.Wondering2:(%d / %d)', [m_sCharName, nX, nY])) else MainOutMessage(Format('%s TAIObject.Wondering3:(%d / %d)', [m_sCharName, nX, nY]));
    end else Stop;
    //end else Stop;
   except

    MainOutMessage(Format('Wonderingai:(%d )', [ncode]));

   end;


  end;




{
begin
  if (Random(30) = 0) then begin
    if (Random(4) = 1) then TurnTo(Random(8))
    else begin
      WalkTo(m_btDirection, False);
      m_boWalking := True;
    end;
  end else if m_boWalking then begin
    SendRefMsg(SM_204, 0, 0, 0, 0, '');
    m_boWalking := False;
  end; }
end;


procedure TPlayObject.Stop;
begin
  if m_boAIStart then begin
    m_boAIStart := False;
    m_ManagedEnvir := nil;
    m_nMoveFailCount := 0;
    m_Path := nil;
    m_nPostion := -1;
    //MainOutMessage(m_sCharName + ' TAIObject.Stop:' + IntToStr(m_PointManager.Count));
    if g_FunctionNPC <> nil then begin
      m_nScriptGotoCount := 0;
      g_FunctionNPC.GotoLable(Self, '@AIStop', False);
    end;
  end;
end;
function TPlayObject.RunToNext(nX, nY: Integer): Boolean;
begin
  Result := RunTo(GetNextDirection(m_nCurrX, m_nCurrY, nX, nY), False);
end;

function TPlayObject.WalkToNext(nX, nY: Integer): Boolean;
begin
  Result := WalkTo(GetNextDirection(m_nCurrX, m_nCurrY, nX, nY), False);
end;

function TPlayObject.GotoNextOne(nX, nY: Integer; boRun: Boolean): Boolean;
var
  I, nStep: Integer;
  Path: TPath;
begin
  Result := False;
  if (abs(nX - m_nCurrX) <= 2) and (abs(nY - m_nCurrY) <= 2) then begin
    if (abs(nX - m_nCurrX) <= 1) and (abs(nY - m_nCurrY) <= 1) then begin
      Result := WalkToNext(nX, nY);
    end else begin
      Result := RunToNext(nX, nY);
    end;
  end;

  if not Result then begin
    g_FindPath.BaseObject := Self;
    Path := g_FindPath.FindPath(m_PEnvir, m_nCurrX, m_nCurrY, nX, nY, boRun, False);

    if Length(Path) > 0 then begin
      for I := 0 to Length(Path) - 1 do begin
        if (Path[I].X <> m_nCurrX) or (Path[I].Y <> m_nCurrY) then begin
          if (abs(Path[I].X - m_nCurrX) >= 2) or (abs(Path[I].Y - m_nCurrY) >= 2) then begin
            Result := RunToNext(Path[I].X, Path[I].Y);
          end else begin
            Result := WalkToNext(Path[I].X, Path[I].Y);
          end;
          break;
        end;
      end;
      Path := nil;
    end;
  end;

  m_RunPos.nAttackCount := 0;
end;
procedure TPlayObject.SearchTarget;
var
  BaseObject, BaseObject18              : TBaseObject;
  i, nC, n10                            : Integer;
begin
  BaseObject18 := nil;
  n10 := 999;

  for i := 0 to m_VisibleActors.Count - 1 do begin
    BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
    if BaseObject.m_boDeath then Continue;
    if IsProperTarget(BaseObject) and (not BaseObject.m_boHideMode) and (not getAInoa(BaseObject.m_sCharName)) then begin
      nC := abs(m_nCurrX - BaseObject.m_nCurrX) + abs(m_nCurrY - BaseObject.m_nCurrY);
      if nC < n10 then begin
        n10 := nC;
        BaseObject18 := BaseObject;
      end;
    end;
  end;
  if BaseObject18 <> nil then SetTargetCreat(BaseObject18);
end;



procedure TPlayObject.RunNotice;                                                                    //004DA588
var
  Msg                                   : TProcessMessage;
  nCode, nOrd                           : Integer;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::RunNotice';
begin
  nCode := 0;
  if m_boEmergencyClose or m_boKickFlag or m_boSoftClose then begin
    if m_boKickFlag then SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
    MakeGhost();
  end else begin
    try
      if not m_boSendNotice then begin
        FeatureChanged;
        SendNotice();
        //m_boSendNotice := True;
        m_dwWaitLoginNoticeOKTick := GetTickCount();
      end else begin
        //        if GetTickCount - m_dwWaitLoginNoticeOKTick > 1200 * 1000 then begin
        //          m_boEmergencyClose := True;
        //        end;
        while GetMessage(@Msg) do begin
          if Msg.wIdent = CM_LOGINNOTICEOK then begin
            m_boLoginNoticeOK := True;
            m_dwRunTick := 0;
            m_dwSearchTick := 0;
            m_boFixedHideMode := False;
            m_boFilterSendMsg := GetDisableSendMsgList(m_sCharName);
            m_boCanDeal := True;
            m_boCanDrop := True;
            m_boCanGetBackItem := True;
            m_boCanWalk := True;
            m_boCanRun := True;
            m_boCanHit := True;
            m_boCanSpell := True;
            m_boCanUseItem := True;

            if g_Config.boPasswordLockSystem then begin                                             //密码保护系统
              if m_boPasswordLocked then begin
                m_boCanGetBackItem := not g_Config.boLockGetBackItemAction;
              end;
              if g_Config.boLockHumanLogin and m_boLockLogon and m_boPasswordLocked then begin
                m_boCanDeal := not g_Config.boLockDealAction;
                m_boCanDrop := not g_Config.boLockDropAction;
                m_boCanUseItem := not g_Config.boLockUserItemAction;
                m_boCanWalk := not g_Config.boLockWalkAction;
                m_boCanRun := not g_Config.boLockRunAction;
                m_boCanHit := not g_Config.boLockHitAction;
                m_boCanSpell := not g_Config.boLockSpellAction;
                m_boCanSendMsg := not g_Config.boLockSendMsgAction;
                m_boObMode := g_Config.boLockInObModeAction;
                m_boAdminMode := g_Config.boLockInObModeAction;
                SysMsg(g_sActionIsLockedMsg + ' 开锁命令: @' + g_GameCommand.UnLock.sCmd, c_Red, t_Hint);
                if not ExecuteScript(g_FunctionNPC, '@仓库锁定') then
                  SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
                    g_sActionIsLockedMsg + #13#10#13#10
                    + '仓库开锁命令: @' + g_GameCommand.UNLOCKSTORAGE.sCmd +
                    #13#10
                    + '仓库加锁命令: @' + g_GameCommand.Lock.sCmd + #13#10
                    + '设置密码命令: @' + g_GameCommand.SETPASSWORD.sCmd + #13#10
                    + '修改密码命令: @' + g_GameCommand.CHGPASSWORD.sCmd);
              end;
            end;

            ExecuteScript(g_ManageNPC, '@LoginNotice');

            if g_Config.boClassicServer then begin
              SendDefMessage(SM_SRVVERSION, Integer(Self), 0, 0, 0, m_VersionManage.ServerVerSion);
            end else begin
              m_BattleVal.BattleVal := m_BattleVal.nMinVal[0] + m_BattleVal.nMinVal[1] +
                m_BattleVal.nMinVal[2] + m_BattleVal.nMinVal[3] + m_BattleVal.nMinVal[4];
              SendDefMessage(SM_BATTLEVAL, Integer(Self), m_BattleVal.BattleVal, 0, 0,
                EnCodeBuffer(@m_BattleVal, SizeOf(TBattleData)), True);

              if g_Config.boTimeBackServer then
                SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 2, 0, m_VersionManage.ServerVerSion);

              if g_Config.boMagicCityServer then
                SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 0, m_VersionManage.ServerVerSion);
{$IF DEMONSERVER = 1}
              if g_Config.boNightMareServer then
                SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 2, m_VersionManage.ServerVerSion);
{$IFEND}
                if g_Config.botimeServer then
                SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 7, 0, m_VersionManage.ServerVerSion);         //时长区
            end;

            if m_boPneuma and (m_PneumaObject <> nil) then begin
              SendRefMsg(RM_TURN,
                m_btDirection,
                m_nCurrX,
                m_nCurrY,
                CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP),
                GetShowName);

              SendRefMsg(RM_510, 1, 0, $16, 0, '');                                                 //元神出现的效果
              if m_PneumaObject is TPlayObject then begin
                if TPlayObject(m_PneumaObject).m_nPneumaLastX <> -1 then begin
                  TPlayObject(m_PneumaObject).m_nPneumaLastX := -1;
                  nOrd := DWORD(Self);
                  m_PneumaObject.SendRefMsg(RM_510, LoWord(nOrd), HiWord(nOrd), 126, 0, '');
                  TPlayObject(m_PneumaObject).ExecuteScript(g_FunctionNPC, '@元神切换触发');
                end;
              end;
            end;
          end;
          Operate(@Msg);
        end;
      end;
    except
      MainOutMessage(sExceptionMsg);
    end;
  end;
end;

procedure TPlayObject.ScatterBagItems(ItemOfCreat: TBaseObject);
var
  i, DropWide, nRate                    : Integer;
  DelList                               : TStringList;
  boDropall                             : Boolean;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  tm                                    : DWORD;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ScatterBagItems';
begin
  if m_btRaceServer <> RC_PLAYOBJECT then begin
    inherited ScatterBagItems(ItemOfCreat);
    Exit;
  end;

  DelList := nil;
  if m_boAngryRing or m_boNoDropItem then Exit;                                                     //不死戒指

  boDropall := False;
  DropWide := 5;
  if g_Config.boDieRedScatterBagAll and (PKLevel >= 2) then begin
    boDropall := True;
  end;
  try
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := pTUserItem(m_ItemList[i]);
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        nRate := g_Config.nDieScatterBagRate;

        if ItemOfCreat <> nil then begin
          if (g_Config.boAttachedSoulAbil) then
            nRate := _MAX(0, nRate - m_HumScatterBagAddRate);                                       //附魂
        end;

        if boDropall or (Random(nRate {3}) = 0) or (CheckSPCode(StdItem.Reserved, RE_SCATTER)) then begin
          if DropItemDown(UserItem, DropWide, True, ItemOfCreat, Self) then begin
            if m_btRaceServer = RC_PLAYOBJECT then begin
              if DelList = nil then DelList := TStringList.Create;
              DelList.AddObject(StdItem.Name, TObject(UserItem.MakeIndex));
            end;
            Dispose(UserItem);
            m_ItemList.Delete(i);
          end;
        end;
      end;
    end;
    if DelList <> nil then begin
      SendMsg(Self, RM_SENDDELITEMLIST, 0, Integer(DelList), 0, 0, '');
    end;
  except
    on E: Exception do begin
      MainOutMessage(sExceptionMsg);
      MainOutMessage(E.Message);
    end;
  end;
end;

procedure TPlayObject.SearchViewRange;
var
  i                                     : Integer;
  nStartX                               : Integer;
  nEndX                                 : Integer;
  nStartY                               : Integer;
  nEndY                                 : Integer;
  n18                                   : Integer;
  n1C                                   : Integer;
  nIdx                                  : Integer;
  n24                                   : Integer;
  MapCellInfo                           : pTMapCellinfo;
  OSObject                              : pTOSObject;
  BaseObject                            : TBaseObject;
  MapItem                               : pTMapItem;
  MapEvent                              : TEvent;
  VisibleBaseObject                     : pTVisibleBaseObject;
  VisibleMapItem                        : pTVisibleMapItem;
  nCheckCode                            : Integer;
  RidePet                               : TRidePet;
resourcestring
  sExceptionMsg1                        = '[Exception] TPlayObject::SearchViewRange Code:%d';
  sExceptionMsg2                        = '[Exception] TPlayObject::SearchViewRange 1-%d %s %s %d %d %d';
begin
  if m_PEnvir = nil then begin
    MainOutMessage('SearchViewRange nil PEnvir');
    Exit;
  end;

//  if m_boOfflineGetGamePoint then Exit;

  n24 := 0;
  try
    nCheckCode := 2;
    for i := m_VisibleItems.Count - 1 downto 0 do begin
      pTVisibleMapItem(m_VisibleItems.Items[i]).nVisibleFlag := 0;
    end;
    nCheckCode := 3;
    for i := m_VisibleEvents.Count - 1 downto 0 do begin
      TEvent(m_VisibleEvents.Items[i]).nVisibleFlag := 0;
    end;
    nCheckCode := 4;
    for i := m_VisibleActors.Count - 1 downto 0 do begin
      pTVisibleBaseObject(m_VisibleActors.Items[i]).nVisibleFlag := 0;
    end;
    nCheckCode := 5;
  except
    MainOutMessage(Format(sExceptionMsg1, [nCheckCode]));
    KickException();
  end;
  nCheckCode := 6;
  nStartX := m_nCurrX - m_nViewRange;
  nEndX := m_nCurrX + m_nViewRange;
  nStartY := m_nCurrY - m_nViewRange;
  nEndY := m_nCurrY + m_nViewRange;
  try
    nCheckCode := 7;
    for n18 := nStartX to nEndX do begin
      nCheckCode := 8;
      for n1C := nStartY to nEndY do begin
        nCheckCode := 9;
        if m_PEnvir.GetMapCellInfo(n18, n1C, MapCellInfo) and
          (MapCellInfo.ObjList <> nil) then begin
          nCheckCode := 10;
          n24 := 1;
          nIdx := 0;
          while (True) do begin
            nCheckCode := 11;
            if MapCellInfo.ObjList.Count <= nIdx then Break;
            OSObject := MapCellInfo.ObjList.Items[nIdx];
            nCheckCode := 12;
            if OSObject = nil then begin                                                            //释放对象
              MapCellInfo.ObjList.Delete(i);
              if MapCellInfo.ObjList.Count > 0 then Continue;
              nCheckCode := 121;
              MapCellInfo.ObjList.free;
              MapCellInfo.ObjList := nil;
              Break;
            end;
            if OSObject <> nil then begin
              nCheckCode := 13;
              if OSObject.btType = OS_MOVINGOBJECT then begin
                nCheckCode := 14;
                if (GetTickCount - OSObject.dwAddTime) >= 60 * 1000 then begin
                  Dispose(OSObject);
                  MapCellInfo.ObjList.Delete(nIdx);
                  if MapCellInfo.ObjList.Count > 0 then Continue;
                  MapCellInfo.ObjList.free;
                  MapCellInfo.ObjList := nil;
                  Break;
                end;
                nCheckCode := 15;
                BaseObject := TBaseObject(OSObject.CellObj);
                if BaseObject <> nil then begin
                  nCheckCode := 16;
                  if not BaseObject.m_boGhost and not
                    BaseObject.m_boFixedHideMode and not BaseObject.m_boObMode then begin
                    nCheckCode := 17;
                    if (m_btRaceServer < RC_ANIMAL) or
                      (m_Master <> nil) or
                      m_boCrazyMode or
                      m_boWantRefMsg or
                      ((BaseObject.m_Master <> nil) and (abs(BaseObject.m_nCurrX - m_nCurrX) <= 3) and (abs(BaseObject.m_nCurrY - m_nCurrY) <= 3)) or
                      (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
                      nCheckCode := 18;
                      UpdateVisibleGay(BaseObject);
                      nCheckCode := 19;
                    end;
                  end;
                end;
              end;
              nCheckCode := 20;
              if m_btRaceServer = RC_PLAYOBJECT then begin
                if OSObject.btType = OS_ITEMOBJECT then begin
                  nCheckCode := 21;

                  if (not pTMapItem(OSObject.CellObj).boForbidClear) and (((m_PEnvir <> nil) and m_PEnvir.m_boClearItem) or ((GetTickCount - OSObject.dwAddTime) > g_Config.dwClearDropOnFloorItemTime)) then begin
                    nCheckCode := 22;
                    Dispose(pTMapItem(OSObject.CellObj));
                    MapCellInfo.ObjList.Delete(nIdx);
                    Dispose(OSObject);                                                              //修正内存错误
                    nCheckCode := 23;
                    if MapCellInfo.ObjList.Count > 0 then Continue;
                    nCheckCode := 24;
                    MapCellInfo.ObjList.free;
                    MapCellInfo.ObjList := nil;
                    Break;
                  end;
                  nCheckCode := 25;
                  MapItem := pTMapItem(OSObject.CellObj);
                  nCheckCode := 28;
                  UpdateVisibleItem(n18, n1C, MapItem);
                  if (MapItem.OfBaseObject <> nil) or (MapItem.DropBaseObject <> nil) then begin
                    nCheckCode := 29;
                    if (GetTickCount - MapItem.dwCanPickUpTick) > g_Config.dwFloorItemCanPickUpTime {2 * 60 * 1000} then begin
                      nCheckCode := 30;
                      MapItem.OfBaseObject := nil;
                      MapItem.DropBaseObject := nil;
                    end else begin
                      nCheckCode := 31;
                      if TBaseObject(MapItem.OfBaseObject) <> nil then begin
                        nCheckCode := 32;
                        if TBaseObject(MapItem.OfBaseObject).m_boGhost then
                          MapItem.OfBaseObject := nil;
                      end;
                      nCheckCode := 33;
                      if TBaseObject(MapItem.DropBaseObject) <> nil then begin
                        nCheckCode := 34;
                        if TBaseObject(MapItem.DropBaseObject).m_boGhost then
                          MapItem.DropBaseObject := nil;
                      end;
                      nCheckCode := 35;
                    end;
                  end;
                end;
                nCheckCode := 36;
                if OSObject.btType = OS_EVENTOBJECT then begin
                  nCheckCode := 37;
                  MapEvent := TEvent(OSObject.CellObj);
                  if MapEvent.m_boVisible then begin
                    nCheckCode := 38;
                    UpdateVisibleEvent(n18, n1C, MapEvent);
                  end;
                  nCheckCode := 39;
                end;
              end
            end;                                                                                    //004B9B81 if OSObject <> nil then begin
            Inc(nIdx);
          end;                                                                                      //while (True) do begin
        end;
      end;                                                                                          //for n1C:= n10 to n14  do begin
    end;                                                                                            //for n18:= n8 to nC do begin
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg2, [n24, m_sCharName, m_sMapName,
        m_nCurrX, m_nCurrY, nCheckCode]));
      MainOutMessage(E.Message);
      KickException();
    end;
  end;
  nCheckCode := 40;
  n24 := 2;
  try
    n18 := 0;
    while (True) do begin
      if m_VisibleActors.Count <= n18 then Break;
      nCheckCode := 41;
      VisibleBaseObject := m_VisibleActors.Items[n18];
      nCheckCode := 42;
      if VisibleBaseObject.nVisibleFlag = 0 then begin
        nCheckCode := 43;
        if m_btRaceServer = RC_PLAYOBJECT then begin
          nCheckCode := 44;
          BaseObject := TBaseObject(VisibleBaseObject.BaseObject);
          nCheckCode := 45;
          if not BaseObject.m_boFixedHideMode and (not BaseObject.m_boGhost) then begin             //01/21 修改防止人物退出时发送重复的消息占用带宽,人物进入隐身模式时人物不消失问题
            nCheckCode := 46;
            SendMsg(BaseObject, RM_DISAPPEAR, 0, 0, 0, 0, '');
          end;
          nCheckCode := 47;
        end;
        m_VisibleActors.Delete(n18);
        nCheckCode := 48;
        Dispose(VisibleBaseObject);
        nCheckCode := 49;
        Continue;
      end;
      nCheckCode := 50;
      if (m_btRaceServer = RC_PLAYOBJECT) and (VisibleBaseObject.nVisibleFlag = 2) then begin
        nCheckCode := 51;
        BaseObject := TBaseObject(VisibleBaseObject.BaseObject);
        nCheckCode := 52;
        if BaseObject <> Self then begin
          nCheckCode := 53;
          if BaseObject.m_boDeath then begin
            nCheckCode := 54;
            if BaseObject.m_boSkeleton then begin
              nCheckCode := 55;
              SendMsg(BaseObject, RM_SKELETON, BaseObject.m_btDirection,
                BaseObject.m_nCurrX, BaseObject.m_nCurrY, 0, '');
              nCheckCode := 56;
            end else begin
              nCheckCode := 57;
              SendMsg(BaseObject, RM_DEATH, BaseObject.m_btDirection, BaseObject.m_nCurrX, BaseObject.m_nCurrY, 0, BaseObject.GetShowName);
              nCheckCode := 58;
            end;
          end else begin
            nCheckCode := 59;
            SendMsg(BaseObject, RM_TURN, BaseObject.m_btDirection, BaseObject.m_nCurrX, BaseObject.m_nCurrY, CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP), BaseObject.GetShowName);

            nCheckCode := 60;
            if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
              nCheckCode := 61;
              if TPlayObject(BaseObject).m_boRideOn and
                TPlayObject(BaseObject).m_boRideFightOn then begin
                nCheckCode := 62;
                RidePet.nFeature := BaseObject.GetFeature(Self);
                nCheckCode := 63;
                if BaseObject.m_boPneuma and (BaseObject.m_PneumaObject <> nil) then begin
                  RidePet.btState := 1 + TPlayObject(BaseObject.m_PneumaObject).m_PetInfo[3].btRideFightSpeed;
                  RidePet.btSoul := TPlayObject(BaseObject.m_PneumaObject).m_PetInfo[3].btSoul;
                end else begin
                  RidePet.btState := 1 + TPlayObject(BaseObject).m_PetInfo[2].btRideFightSpeed;
                  RidePet.btState := 1 + TPlayObject(BaseObject).m_PetInfo[2].btSoul;
                end;
                nCheckCode := 64;
                SendMsg(BaseObject, RM_SITDOWN, BaseObject.m_btDirection,
                  MakeLong(BaseObject.m_nCurrX, BaseObject.m_nCurrY),
                  BaseObject.GetFeature(Self), 1, EnCodeBuffer(@RidePet, SizeOf(TRidePet)));
              end;
            end;
            nCheckCode := 65;
          end;
        end;
      end;
      Inc(n18);
    end;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg2, [n24, m_sCharName, m_sMapName,
        m_nCurrX, m_nCurrY, nCheckCode]));
      KickException();
    end;
  end;
  try
    i := 0;
    while (True) do begin
      if m_VisibleItems.Count <= i then Break;
      VisibleMapItem := m_VisibleItems.Items[i];
      if VisibleMapItem.nVisibleFlag = 0 then begin
        SendMsg(Self, RM_ITEMHIDE, 0, Integer(VisibleMapItem.MapItem),
          VisibleMapItem.nX, VisibleMapItem.nY, '');
        m_VisibleItems.Delete(i);
        Dispose(VisibleMapItem);
        Continue;
      end;                                                                                          //004B9F6C
      if VisibleMapItem.nVisibleFlag = 2 then begin
        SendMsg(Self, RM_ITEMSHOW, VisibleMapItem.wLooks, Integer(VisibleMapItem.MapItem), VisibleMapItem.nX, VisibleMapItem.nY, VisibleMapItem.sName);
      end;
      Inc(i);
    end;
    i := 0;
    while (True) do begin
      if m_VisibleEvents.Count <= i then Break;
      MapEvent := m_VisibleEvents.Items[i];
      if MapEvent.nVisibleFlag = 0 then begin
        SendMsg(Self, RM_HIDEEVENT, 0, Integer(MapEvent), MapEvent.m_nX,
          MapEvent.m_nY, '');
        m_VisibleEvents.Delete(i);
        Continue;
      end;
      if MapEvent.nVisibleFlag = 2 then begin
        SendMsg(Self, RM_SHOWEVENT,
          MapEvent.m_nEventType,
          Integer(MapEvent),
          MakeLong(MapEvent.m_nX, MapEvent.m_nEventParam),
          MapEvent.m_nY,
          '');
      end;
      Inc(i);
    end;
    //清理物品结束
    if ((m_PEnvir <> nil) and m_PEnvir.m_boClearItem) then
      m_PEnvir.m_boClearItem := False;
  except
    MainOutMessage(m_sCharName + ',' +
      m_sMapName + ',' +
      IntToStr(m_nCurrX) + ',' +
      IntToStr(m_nCurrY) + ',' +
      ' SearchViewRange 3');

    KickException();
  end;
end;

///////兼容客户端/////////Begin////////////////////

{发送添加交易物品}

procedure TPlayObject.SendAddDealItem(UserItem: pTUserItem);
begin
  if UserItem = nil then Exit;
  SendDefMessage(SM_DEALADDITEM_OK, 0, 0, 0, 0, '');
  if (m_DealCreat <> nil) and (m_DealCreat.m_btRaceServer = RC_PLAYOBJECT) then begin
    //必须在这里就要保证下面的安全
    if Assigned(TPlayObject(m_DealCreat).m_VersionManage) then
    try
      TPlayObject(m_DealCreat).m_VersionManage.OnSendAddDealItem(Self, UserItem);
    except
      MainOutMessage(Format('TPlayObject::OnSendAddDealItem SoftVersionDate:%d', [TPlayObject(m_DealCreat).m_VersionManage.SoftVersionDate]));
    end;

    //    if (TPlayObject(m_DealCreat).m_nSoftVersionDateEx = 0) then begin
    //      VER19990SendAddDealItem(UserItem);
    //    end else begin
    //      VER19990SendAddDealItem(UserItem);
    //    end;

    m_DealCreat.m_DealLastTick := GetTickCount();
    m_DealLastTick := GetTickCount();
  end;
end;

{删除交易框物品}

procedure TPlayObject.SendDelDealItem(UserItem: pTUserItem);
begin
  if UserItem = nil then Exit;
  SendDefMessage(SM_DEALDELITEM_OK, 0, 0, 0, 0, '');
  if (m_DealCreat <> nil) and (m_DealCreat.m_btRaceServer = RC_PLAYOBJECT) then begin

    if Assigned(TPlayObject(m_DealCreat).m_VersionManage) then
    try
      TPlayObject(m_DealCreat).m_VersionManage.OnSendDelDealItem(Self, UserItem);
    except
      MainOutMessage(Format('TPlayObject::OnSendDelDealItem SoftVersionDate:%d', [TPlayObject(m_DealCreat).m_VersionManage.SoftVersionDate]));
    end;

    //    if (TPlayObject(m_DealCreat).m_nSoftVersionDateEx = 0) then begin
    //      VER19990SendDelDealItem(UserItem);
    //    end else begin
    //      VER19990SendDelDealItem(UserItem);
    //    end;

    m_DealCreat.m_DealLastTick := GetTickCount();
    m_DealLastTick := GetTickCount();
  end;
end;

{获取玩家包裹物品数据}

procedure TPlayObject.ClientQueryBagItems;
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnQueryBagItems(Self);
  except
    MainOutMessage(Format('TPlayObject::OnQueryBagItems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;

  if m_boBagSend then
    ClientSendBagOrder();                                                                           {包裹顺序}
end;

//处理添加包裹物品命令

procedure TPlayObject.SendAddItem(UserItem: pTUserItem);
begin
  {兼容客户端}
  if UserItem = nil then Exit;
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendAddItem(Self, UserItem);
  except
    MainOutMessage(Format('TPlayObject::OnSendAddItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

{发送删除的物品}

procedure TPlayObject.SendDelItems(UserItem: pTUserItem);
begin
  if UserItem = nil then Exit;
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendDelItems(Self, UserItem);
  except
    MainOutMessage(Format('TPlayObject::OnSendDelItems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;

end;

{更新物品数据}

procedure TPlayObject.SendUpdateItem(UserItem: pTUserItem; boDelay: Boolean = True);
begin
  if UserItem = nil then Exit;
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendUpdateItem(Self, UserItem, boDelay);
  except
    MainOutMessage(Format('TPlayObject::OnSendUpdateItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;

end;

//查询玩家装备

procedure TPlayObject.ClientQueryUserState(BaseObject: TBaseObject; nX, nY: Integer);
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::ClientQueryUserState Code = %d';
var
  UserItem                              : pTUserItem;
  Hum                                   : TPlayObject;
  nCheckCode                            : Integer;
begin
  nCheckCode := 0;
  try
    if BaseObject = nil then Exit;
    nCheckCode := 1;
    if not (BaseObject is TPlayObject) then Exit;
    //    {只允许查看玩家和心魔的装备}
    //    if (BaseObject.m_btRaceServer <> RC_PLAYOBJECT) then Exit;

        {只允许查看夺宝心魔的装备}
    //    if (BaseObject.m_btRaceServer = RC_EVIL) and (BaseObject.m_btRaceImg <> 253) then Exit;

        //关灯模式

    if (m_PEnvir.m_MapFlag.boSECRET and ((m_PEnvir.m_MapFlag.btSECRETRule and SECRET_RULE_DISABLEQUERY) <> 0)) then
    begin
      SysMsg('该地图不允许查看对手信息', c_Red, t_Hint);
      Exit;
    end;

    if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
      if (TPlayObject(BaseObject).m_boSecretMode) and (not TPlayObject(BaseObject).m_boCheckItem) then begin
        SysMsg('对方处于神秘人模式,不允许查看装备信息', c_Red, t_Hint);
        Exit;
      end;
    end;

    nCheckCode := 2;
    {查看死亡玩家的装备}
    if (nX = 0) and (nY = 0) then begin
      if (BaseObject <> nil) and (not BaseObject.m_boGhost) then begin
        nX := BaseObject.m_nCurrX;
        nY := BaseObject.m_nCurrY;
      end;
    end;
    nCheckCode := 3;
    if (not CretInNear10XY(BaseObject, nX, nY)) then Exit;

    nCheckCode := 4;
    if Assigned(m_VersionManage) then
    try
      m_VersionManage.OnQueryUserState(Self, BaseObject);
    except
      MainOutMessage(Format('TPlayObject::OnQueryUserState SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
    end;

    nCheckCode := 5;
    if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
      with TPlayObject(BaseObject) do
      begin
        //发送骑站数据
        nCheckCode := 6;
        if m_boRideOn then begin
          if m_boPneuma and (m_PneumaObject <> nil) then begin
            Hum := TPlayObject(BaseObject.m_PneumaObject);                                          //元神骑乘
            Hum.GetUserItemByMakeIndex(Hum.m_PetInfo[3].nMakeIndex, UserItem);
          end else begin
            GetUserItemByMakeIndex(m_PetInfo[2].nMakeIndex, UserItem);                              //本体骑乘
          end;

          Self.SendPetAttribute(TPlayObject(BaseObject), 1, UserItem);
        end;
        nCheckCode := 7;
        //发送魂佑灵兽信息
        if m_boBeast then begin
          GetUserItemByMakeIndex(m_PetInfo[5].nMakeIndex, UserItem);
          Self.SendPetAttribute(TPlayObject(BaseObject), 0, UserItem);
        end;
      end;

      nCheckCode := 8;


      nCheckCode := 9;
      SendDemonDanInfo(0, BaseObject);
      SendConstellationStarLv(BaseObject);
      nCheckCode := 10;

      {脚本触发}
      m_sScriptParam[0] := BaseObject.m_sCharName;
      ExecuteScript(g_FunctionNPC, '@查询玩家装备');
    end;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
end;

{发送宠物包裹数据}

procedure TPlayObject.SendPetBagItems;
begin
  SendDefMessage(SM_PETBAGSIZE, Integer(Self), 0, m_nPetShopSize, m_nPetBagSize, '');
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendPetBagItems(Self);
  except
    MainOutMessage(Format('TPlayObject::OnSendPetBagItems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

procedure TPlayObject.SendAddPetItem(UserItem: pTUserItem);
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendAddPetItem(Self, UserItem);
  except
    MainOutMessage(Format('TPlayObject::OnSendAddPetItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

{发送仓库物品列表}

procedure TPlayObject.SendSaveItemList(nBaseObject: Integer; boFast: Boolean);
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendSaveItemList(Self, nBaseObject, boFast);
  except
    MainOutMessage(Format('TPlayObject::OnSendSaveItemList SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//发送身上物品

procedure TPlayObject.SendUseitems;
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendUseitems(Self);
  except
    MainOutMessage(Format('TPlayObject::OnSendUseitems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//发送内视装备物品

procedure TPlayObject.SendEntopticItems;
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendEntopticItems(Self);
  except
    MainOutMessage(Format('TPlayObject::OnSendEntopticItems SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//发送我的摊位物品列表给某个玩家

procedure TPlayObject.SendShopItems(BaseObject: TBaseObject; opcode: word);
var
  PlayObject                            : TPlayObject;
begin
  if not (BaseObject is TPlayObject) then Exit;
  PlayObject := BaseObject as TPlayObject;
  if Assigned(PlayObject.m_VersionManage) then
  try
    PlayObject.m_VersionManage.OnSendShopItems(Self, PlayObject, opcode);
  except
    MainOutMessage(Format('TPlayObject::OnSendShopItems SoftVersionDate:%d', [PlayObject.m_VersionManage.SoftVersionDate]));
  end;

  //  if (PlayObject.m_nSoftVersionDateEx = 0) then begin
  //    VER19990SendShopItems(PlayObject,opcode);
  //  end else begin
  //    VER19990SendShopItems(PlayObject,opcode);
  //  end;

end;

procedure TPlayObject.SendTigerItem();
begin
  if m_boPneuma and not m_boInosculatePneuma then Exit;

  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendTigerItem(Self);
  except
    MainOutMessage(Format('TPlayObject::OnSendTigerItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

///////兼容客户端////////END/////////////////////

procedure TPlayObject.SendAddMagic(UserMagic: pTUserMagic);                                         //004D12F4
var
  ClientMagic                           : TClientMagic;
  pMagicOrder                           : string;
begin
  UserMagic.GetClientMagic(@ClientMagic);
  m_defMsg := MakeDefaultMsg(SM_ADDMAGIC, 0, 0, 0, 1);
  SendSocket(@m_defMsg, EnCodeBuffer(@ClientMagic, SizeOf(TClientMagic)));

  //处理铁血神技技能顺序
{  if UserMagic.GetMagIdx in [SKILL_220..SKILL_235] then begin
    pMagicOrder := ReverseString(m_MagicOrder);
    if UserMagic.GetMagIdx in [SKILL_220, SKILL_224, SKILL_228, SKILL_232] then
      pMagicOrder := pMagicOrder + '1';
    if UserMagic.GetMagIdx in [SKILL_221, SKILL_225, SKILL_229, SKILL_233] then
      pMagicOrder := pMagicOrder + '2';
    if UserMagic.GetMagIdx in [SKILL_222, SKILL_226, SKILL_230, SKILL_234] then
      pMagicOrder := pMagicOrder + '3';
    if UserMagic.GetMagIdx in [SKILL_223, SKILL_227, SKILL_231, SKILL_235] then
      pMagicOrder := pMagicOrder + '4';

    m_MagicOrder := ReverseString(pMagicOrder);
    SendDefMessage(1650, 0, HexToInt('$' + m_MagicOrder), 220, 0, '');
  end;
       }
end;

//发送给客户端调整点数值

procedure TPlayObject.SendAdjustBonus;
var
  sSENDMSG                              : string;
begin
  m_defMsg := MakeDefaultMsg(SM_ADJUST_BONUS, m_nBonusPoint, 0, 0, 0);
  sSENDMSG := '';
  case m_btJob of
    0: sSENDMSG := EnCodeBuffer(@g_Config.BonusAbilofWarr, SizeOf(TNakedAbility))
      + '/' +
        EnCodeBuffer(@m_BonusAbil, SizeOf(TNakedAbility)) + '/' +
        EnCodeBuffer(@g_Config.NakedAbilofWarr, SizeOf(TNakedAbility));
    1: sSENDMSG := EnCodeBuffer(@g_Config.BonusAbilofWizard,
        SizeOf(TNakedAbility)) + '/' +
      EnCodeBuffer(@m_BonusAbil, SizeOf(TNakedAbility)) + '/' +
        EnCodeBuffer(@g_Config.NakedAbilofWizard, SizeOf(TNakedAbility));
    2: sSENDMSG := EnCodeBuffer(@g_Config.BonusAbilofTaos, SizeOf(TNakedAbility))
      + '/' +
        EnCodeBuffer(@m_BonusAbil, SizeOf(TNakedAbility)) + '/' +
        EnCodeBuffer(@g_Config.NakedAbilofTaos, SizeOf(TNakedAbility));
  end;
  SendSocket(@m_defMsg, sSENDMSG);
end;

procedure TPlayObject.SendChangeGuildName;
begin
  if m_MyGuild <> nil then begin
    SendDefMessage(SM_CHANGEGUILDNAME, 0, TGuild(m_MyGuild).btGuildFlag, 0, 0, TGuild(m_MyGuild).sGuildName + '/' + m_sGuildRankName);
  end else begin
    SendDefMessage(SM_CHANGEGUILDNAME, 0, 0, 0, 0, '');
  end;
end;

//直接发送消息(消息已经处理完毕)

procedure TPlayObject.SendDefMessage(wIdent: word; nRecog: Integer; nParam,
  nTag, nSeries: word; sMsg: string; boEn: Boolean);                                                //004CAD6C
begin
  m_defMsg := MakeDefaultMsg(wIdent, nRecog, nParam, nTag, nSeries);
  if sMsg <> '' then
  begin
    if boEn then
      SendSocket(@m_defMsg, sMsg)
    else
      SendSocket(@m_defMsg, EnCodeString(sMsg));
  end
  else
    SendSocket(@m_defMsg, '');
end;

procedure TPlayObject.SendDelItemList(ItemList: TStringList);
var
  i                                     : Integer;
  s10                                   : string;
begin
  s10 := '';
  for i := 0 to ItemList.Count - 1 do begin
    s10 := s10 + ItemList.Strings[i] + '/' +
      IntToStr(Integer(ItemList.Objects[i])) + '/';
  end;
  m_defMsg := MakeDefaultMsg(SM_DELITEMS, 0, 0, 0, ItemList.Count);
  SendSocket(@m_defMsg, EnCodeString(s10));

  SendDelayMsg(Self, CM_QUERYBAGITEMS, 0, 0, 0, 0, '', 300);
end;

procedure TPlayObject.SendDelMagic(UserMagic: pTUserMagic);
var
  pMagicOrder                           : string;
  i, nMaxLen                            : Integer;
  MyMagic                               : pTUserMagic;
begin
  //处理铁血神技技能顺序

  m_defMsg := MakeDefaultMsg(SM_DELMAGIC, UserMagic.GetMagIdx, 0, 0, 1);
  SendSocket(@m_defMsg, '')
end;

//装载并发送好友列表

procedure TPlayObject.SendFiendList(const b: ShortInt = -1);
var
  i                                     : Integer;
  sMsg, sAmbit                          : string;
  ClanAmbit                             : pTClanAmbit;
begin
  //发送好友名单
  if (b = -1) or (b = 0) then begin
    sMsg := '';
    for i := 0 to m_FriendsList.Count - 1 do begin
      sMsg := sMsg + m_FriendsList[i] + '/';
    end;
    if Length(sMsg) > 0 then
      SendDefMessage(SM_SENDFRIENDS, 0, 0, 0, 0, sMsg);
  end;
  //发送师傅名单
  if (b = -1) or (b = 1) then begin
    if (Length(m_sMasterName[1]) > 0) and (not m_boMaster) then
      SendDefMessage(SM_SENDFRIENDS, 0, 1, 0, 0, m_sMasterName[1]);
  end;
  //发送徒弟名单
  if (b = -1) or (b = 2) then begin
    sMsg := '';
    if m_boMaster then begin
      for i := 1 to 3 do begin
        if m_sMasterName[i] <> '' then
          sMsg := sMsg + m_sMasterName[i] + '/';
      end;
      SendDefMessage(SM_SENDFRIENDS, 0, 2, 0, 0, sMsg);
    end;
  end;
  //发送配偶名单
  if (b = -1) or (b = 3) then begin
    if (Length(m_sDearName) > 0) then
      SendDefMessage(SM_SENDFRIENDS, 0, 3, 0, 0, m_sDearName);
  end;

  //发送宗族名单
  if (b = -1) or (b = 4) then begin
    sMsg := '';
    if (m_MyClan <> nil) then begin
      with TClan(m_MyClan) do begin
        sMsg := Format('%s/%s/%d,%d,%d,%d/', [m_sClanName, ChiefName, btClanKind, nMaxMember, nActivity, btTaskDifficuty]);
        for i := 0 to m_MemberList.Count - 1 do begin
          ClanAmbit := pTClanAmbit(m_MemberList.GetValues(m_MemberList.Keys[i]));
          if (ClanAmbit.Ambit > 2) then begin
            if (ClanAmbit.Ambit mod 2) = 0 then
              sAmbit := '2'
            else
              sAmbit := '1';
          end else
            sAmbit := '0';
          sMsg := Format('%s%s,%d,%d/%s/', [sMsg, sAmbit, m_nHiContribution, m_nCurContribution, m_MemberList.Keys[i]])
        end;
      end;
      SendDefMessage(SM_SENDFRIENDS, 0, 4, 0, 0, sMsg);
    end;
  end;
end;

procedure TPlayObject.SendGroupMembers;
var
  i                                     : Integer;
  PlayObject                            : TPlayObject;
  sSENDMSG                              : string;
begin
  sSENDMSG := '';
  for i := 0 to m_GroupMembers.Count - 1 do begin
    PlayObject := TPlayObject(m_GroupMembers.Objects[i]);
    sSENDMSG := sSENDMSG + PlayObject.m_sCharName + '/';
  end;
  for i := 0 to m_GroupMembers.Count - 1 do begin
    PlayObject := TPlayObject(m_GroupMembers.Objects[i]);
    PlayObject.SendDefMessage(SM_GROUPMEMBERS, 0, 0, 0, 0, sSENDMSG);
  end;
end;

procedure TPlayObject.SendGuildTowerInfo();
var
  sGuildJobMsg                          : string;
  i, ii, j, nTowerGrade                 : Integer;
  nPermission                           : Integer;
resourcestring
  sOfficialMsg                          = '%d/%d/%d/%d/%d/%s/';
begin
  if m_MyGuild = nil then Exit;
  try
    nTowerGrade := _MIN(10, TGuild(m_MyGuild).btTowerGrade);
    if nTowerGrade > 0 then begin
      sGuildJobMsg := TGuild(m_MyGuild).GetChiefName + '/';
      for i := 1 to 10 do begin
        sGuildJobMsg := sGuildJobMsg + Format(sOfficialMsg, [i, nGuildOfficialCount[nTowerGrade][i], nGuildOfficialCountMax[i], btGuildOfficialCrony[i], nGuildOfficialPrice[i], sGuildOfficial[i]]);
      end;
      if (m_nGuildRankNo in [1..10]) then nPermission := nGuildOfficialPermission[m_nGuildRankNo] else nPermission := 1024;

      g_LargePacketManage.Init;
      g_LargePacketManage.WriteBuffer(m_GuildTowerInfo, SizeOf(TGuildTowerInfo));
      g_LargePacketManage.WriteString(sGuildJobMsg);
      m_defMsg := MakeDefaultMsg(SM_GUILDOFFICIAL, m_nGuildGold, nTowerGrade, nPermission, 0);
      SendSocket(@m_defMsg, g_LargePacketManage.GetMsg);
    end;
  except
    on E: Exception do begin
      MainOutMessage('procedure TPlayObject.SendGuildTowerInfo');
      MainOutMessage(E.Message);
    end;
  end;
end;

procedure TPlayObject.SendGuildTowerRes();
var
  Guild                                 : TGuild;
  TowerRes                              : TGuildTowerRes;
begin
  if m_MyGuild = nil then Exit;
  Guild := TGuild(m_MyGuild);
  TowerRes := Guild.GuildTowerRes;
  TowerRes.nOreMax := 3000;
  TowerRes.nGemMax := 3000;
  TowerRes.nWoodMax := 3000;
  TowerRes.nBarMax := 3000;
  TowerRes.nRockMax := 3000;
  m_defMsg := MakeDefaultMsg(SM_GUILDTOWER, Guild.dwGuildGold, 1, 0, 0);
  SendSocket(@m_defMsg, EnCodeBuffer(@TowerRes, SizeOf(TGuildTowerRes)));
end;

procedure TPlayObject.SendLogon;
var
  MessageBodyL                          : TMessageBodyL;
  nRecog, nMaxDamage                    : Integer;
begin
  m_defMsg := MakeDefaultMsg(SM_NEWMAP, Integer(Self), m_nCurrX, m_nCurrY, 10240);
  SendSocket(@m_defMsg, EnCodeString(m_PEnvir.m_MapFlag.sClientMapName));

  MessageBodyL.nFeature := GetFeatureToLong(Self);
  MessageBodyL.nCharStatus := m_nCharStatus;
  if m_boAllowGroup then
    MessageBodyL.nFlag := MakeLong(MakeWord(1, 0), GetGender)
  else
    MessageBodyL.nFlag := MakeLong(0, GetGender);
  MessageBodyL.nDressShape := m_nDressShape;

  m_defMsg := MakeDefaultMsg(SM_LOGON, Integer(Self), m_nCurrX, m_nCurrY, MakeWord(m_btDirection, m_btGender));
  SendSocket(@m_defMsg, EnCodeBuffer(@MessageBodyL, SizeOf(TMessageBodyL)));


end;

procedure TPlayObject.SendMagic_LvExp_Msg(const UserMagic: pTUserMagic; dwDelay: LongWord);
begin
  Assert(UserMagic <> nil, 'TPlayObject::SendMagic_LvExp_Msg');
  if UserMagic.GetMagIdx = 184 then begin
    //终极连击  需要发送添加的技能的消息来更新最高连击点...
    SendAddMagic(UserMagic);
    Exit;
  end;
  SendDelayMsg(Self, RM_MAGIC_LVEXP,
    0,
    UserMagic.GetMagIdx,
    UserMagic.btLevel,
    UserMagic.nTranPoint,
    '',
    dwDelay);
end;

//地图描述命令的处理

procedure TPlayObject.SendMapDescription;
var
  nMUSICID                              : Integer;
  sMapDesc                              : string;
begin
  nMUSICID := 0;
  if m_PEnvir.m_MapFlag.boMUSIC then nMUSICID := m_PEnvir.m_MapFlag.nMUSICID;

  if m_sMapNewDesc <> '' then
    sMapDesc := m_sMapNewDesc
  else
    sMapDesc := m_PEnvir.m_sMapDesc;
  if m_boFlyer then
    SendDefMessage(SM_MAPDESCRIPTION, nMUSICID, 0, 0, 0, sMapDesc + '上空')
  else
    SendDefMessage(SM_MAPDESCRIPTION, nMUSICID, 0, 0, 0, sMapDesc)
end;

//上线时,发送我的好友到客户端,同时向在线好友发送我的状态
//state=0 表示下线或隐身

procedure TPlayObject.SendMeOnlineState(State: byte; b: ShortInt = -1);
var
  i                                     : Integer;
  sOtherName                            : string;
  Hum                                   : TPlayObject;
begin
  if (b = -1) or (b = 0) then begin
    for i := 0 to m_FriendsList.Count - 1 do begin
      //检查对方的状态
      sOtherName := m_FriendsList[i];
      Hum := UserEngine.GetPlayObject(sOtherName);
      //对方在线
      if (Hum <> nil) and (not Hum.m_boDeath) and (not Hum.m_boGhost) then begin
        if (Hum.m_MyGuild <> nil) then
          sOtherName := sOtherName + Chr($00) + TGuild(Hum.m_MyGuild).sGuildName;

        if State <> 0 then
          SendDefMessage(SM_PLAYERONLINE, State, 0, MakeWord(Hum.m_btAmbitLevel, Hum.m_btAmbitKind), MakeWord(Hum.m_WAbil.level, Hum.m_btJob), sOtherName);

        //向对方发送好友上/下线消息
        sOtherName := m_sCharName;
        if (m_MyGuild <> nil) then
          sOtherName := sOtherName + Chr($00) + TGuild(m_MyGuild).sGuildName;
        Hum.SendDefMessage(SM_PLAYERONLINE, State, 0, MakeWord(m_btAmbitLevel, m_btAmbitKind), MakeWord(m_WAbil.level, m_btJob), sOtherName);
      end;
    end;
  end;

  //发送师傅上线通知
  if (b = -1) or (b = 1) then begin
    if m_boMaster then begin
      for i := 1 to 3 do begin
        if m_sMasterName[i] = '' then Continue;
        sOtherName := m_sMasterName[i];
        Hum := UserEngine.GetPlayObject(sOtherName);
        if (Hum <> nil) and (not Hum.m_boDeath) and (not Hum.m_boGhost) then begin
          if (Hum.m_MyGuild <> nil) then
            sOtherName := sOtherName + Chr($00) + TGuild(Hum.m_MyGuild).sGuildName;
          if State <> 0 then                                                                        //发送给自己 师傅在线
            SendDefMessage(SM_PLAYERONLINE, State, 2, MakeWord(Hum.m_btAmbitLevel, Hum.m_btAmbitKind), MakeWord(Hum.m_WAbil.level, Hum.m_btJob), sOtherName);

          //向对方发送上线消息                                                                        //发送给师傅,徒弟上线
          sOtherName := m_sCharName;
          if (m_MyGuild <> nil) then
            sOtherName := sOtherName + Chr($00) + TGuild(m_MyGuild).sGuildName;
          Hum.SendDefMessage(SM_PLAYERONLINE, State, 1, MakeWord(m_btAmbitLevel, m_btAmbitKind), MakeWord(m_WAbil.level, m_btJob), sOtherName);
        end;
      end;
    end;
  end;

  //发送徒弟上线通知
  if (b = -1) or (b = 2) then begin
    if not m_boMaster and (m_sMasterName[1] <> '') then begin
      sOtherName := m_sMasterName[1];
      Hum := UserEngine.GetPlayObject(sOtherName);
      if (Hum <> nil) and (not Hum.m_boDeath) and (not Hum.m_boGhost) then begin
        if (Hum.m_MyGuild <> nil) then
          sOtherName := sOtherName + Chr($00) + TGuild(Hum.m_MyGuild).sGuildName;
        if State <> 0 then                                                                          //发送给自己 师傅在线
          SendDefMessage(SM_PLAYERONLINE, State, 1, MakeWord(Hum.m_btAmbitLevel, Hum.m_btAmbitKind), MakeWord(Hum.m_WAbil.level, Hum.m_btJob), sOtherName);

        //向对方发送上线消息                                                                        //发送给师傅,徒弟上线
        sOtherName := m_sCharName;
        if (m_MyGuild <> nil) then
          sOtherName := sOtherName + Chr($00) + TGuild(m_MyGuild).sGuildName;
        Hum.SendDefMessage(SM_PLAYERONLINE, State, 2, MakeWord(m_btAmbitLevel, m_btAmbitKind), MakeWord(m_WAbil.level, m_btJob), sOtherName);
      end;
    end;
  end;

  //发送夫妻上线通知
  if (b = -1) or (b = 3) then begin
    if (m_DearHuman <> nil) and (not m_DearHuman.m_boDeath) and (not m_DearHuman.m_boGhost) then begin
      sOtherName := m_sDearName;
      if (m_DearHuman.m_MyGuild <> nil) then
        sOtherName := sOtherName + Chr($00) + TGuild(m_DearHuman.m_MyGuild).sGuildName;
      if State <> 0 then
        SendDefMessage(SM_PLAYERONLINE, State, 3, MakeWord(m_DearHuman.m_btAmbitLevel, m_DearHuman.m_btAmbitKind), MakeWord(m_DearHuman.m_WAbil.level, m_DearHuman.m_btJob), sOtherName);

      //向对方发送上线消息
      sOtherName := m_sCharName;
      if (m_MyGuild <> nil) then
        sOtherName := sOtherName + Chr($00) + TGuild(m_MyGuild).sGuildName;
      m_DearHuman.SendDefMessage(SM_PLAYERONLINE, State, 3, MakeWord(m_btAmbitLevel, m_btAmbitKind), MakeWord(m_WAbil.level, m_btJob), sOtherName);
    end;
  end;

  //宗族消息
  if (b = -1) or (b = 4) then begin
    if (m_MyClan <> nil) then begin
      for i := 0 to TClan(m_MyClan).m_MemberList.Count - 1 do begin
        sOtherName := TClan(m_MyClan).m_MemberList.Keys[i];
        Hum := UserEngine.GetPlayObject(sOtherName);
        //对方在线
        if (Hum <> nil) and (not Hum.m_boDeath) and (not Hum.m_boGhost) then begin
          if (Hum.m_MyGuild <> nil) then
            sOtherName := sOtherName + Chr($00) + TGuild(Hum.m_MyGuild).sGuildName;

          if State <> 0 then
            SendDefMessage(SM_PLAYERONLINE, State, 4, MakeWord(Hum.m_btAmbitLevel, Hum.m_btAmbitKind), MakeWord(Hum.m_WAbil.level, Hum.m_btJob), sOtherName);

          //向对方发送好友上/下线消息
          sOtherName := m_sCharName;
          if (m_MyGuild <> nil) then
            sOtherName := sOtherName + Chr($00) + TGuild(m_MyGuild).sGuildName;
          Hum.SendDefMessage(SM_PLAYERONLINE, State, 4, MakeWord(m_btAmbitLevel, m_btAmbitKind), MakeWord(m_WAbil.level, m_btJob), sOtherName);
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.SendNearbyGuildMemberList;
var
  i                                     : Integer;
  Str                                   : string;
  BaseObjectList                        : TList;
  BaseObject                            : TBaseObject;
begin
  Str := '';
  BaseObjectList := TList.Create;
  m_PEnvir.GetRangeBaseObject(m_nCurrX, m_nCurrY, 10, True, BaseObjectList);
  for i := 0 to BaseObjectList.Count - 1 do begin
    BaseObject := TBaseObject(BaseObjectList.Items[i]);
    if (BaseObject.m_btRaceServer <> RC_PLAYOBJECT) then Continue;
    if (BaseObject.m_boPneuma) or (BaseObject = Self) or (BaseObject.m_MyGuild <> m_MyGuild) then Continue;
    Str := Str + BaseObject.m_sCharName + '/' + IntToStr(BaseObject.m_nGuildGold) + '/';
  end;
  BaseObjectList.free;
  if Str <> '' then begin
    SendDefMessage(SM_GUILDOFFICIALPLAYER, 0, 0, 0, 0, Str);
  end;
end;

//极品阁

procedure TPlayObject.SendNonSuchPavilion(nSerial: Integer);
var
  G                                     : TGuild;
  i, nCount                             : Integer;
  UserItem                              : pTUserItem;
  boView                                : Boolean;
begin
  if m_MyGuild = nil then Exit;
  G := TGuild(m_MyGuild);
  if not G.boTowerStatus then begin
    SendDefMessage(SM_TREASUREPAVILION, 0, 4, 0, 0, '通灵塔资源不足被封闭,无法进入极品阁。');
    Exit;
  end;
  try
    boView := False;
    nCount := Length(G.m_TreasurePavilion);
    for i := 0 to nCount - 1 do begin
      if G.m_TreasurePavilion[i].btPos = nSerial then begin
        boView := (G.m_TreasurePavilion[i].btState = 4);
        Break;
      end;
    end;

    m_boInNonSuchPavilion := False;
    if not boView then begin
      GetUserItemByName('灵皓石', UserItem);
      if UserItem = nil then begin
        SendDefMessage(SM_TREASUREPAVILION, 0, 4, 0, 0, '您包裹内没有灵皓石,请到商城购买。');
        Exit;
      end else begin
        m_boInNonSuchPavilion := True;
        SendDelItems(UserItem);
        DelBagItem(UserItem.MakeIndex, '灵皓石');
        WeightChanged;
        m_sScriptParam[0] := IntToStr(nSerial);
        ExecuteScript(g_GuildTowerNPC, '@进入极品阁');
      end;
    end;

    if Assigned(m_VersionManage) then
    try
      m_VersionManage.OnSendNonSuchPavilion(Self, G);
    except
      MainOutMessage(Format('TPlayObject::OnSendNonSuchPavilion SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
    end;

  except
    on E: Exception do begin
      MainOutMessage('procedure TPlayObject.SendTreasurePavilion');
      MainOutMessage(E.Message);
    end;
  end;
end;

//发送公告

procedure TPlayObject.SendNotice;                                                                   //004DA490
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::SendNotice Code=%d';
type
  TREC = packed record
    n: byte;
    m: word;
  end;
var
  LoadList                              : TStringList;
  sNoticesg                             : string;
  Rec                                   : array[0..5] of TREC;
  i, nCode, nType                       : Integer;
  nCheckCode                            : Integer;
  MessageBodyW                          : TMessageBodyW;
begin
{$IF COUNTRYSYSTEM = 1}
  //根据官职等级获得官职名称
  if m_boPneuma and (m_PneumaObject <> nil) then begin
    m_btCountry := m_PneumaObject.m_btCountry;
  end;
  if (m_btCountry > 0) and (g_OffPosList.Count > 0) then begin
    if m_btOfficialPos >= g_OffPosList.Count then
      m_sOffName := g_OffPosList[g_OffPosList.Count - 1]
    else
      m_sOffName := g_OffPosList[m_btOfficialPos];
  end;
{$IFEND}
  nCheckCode := 0;
  try
    SendDefMessage(1667, -1, 0, 0, 0, '');                                                          //未知
    {未知}
    QuerySubAbility();

    if g_Config.boClassicServer then begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 0, 0, 0, m_VersionManage.ServerVerSion);
    end else begin
      if g_Config.boTimeBackServer then
        SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 2, 0, m_VersionManage.ServerVerSion);

      if g_Config.boMagicCityServer then
        SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 0, m_VersionManage.ServerVerSion);
{$IF DEMONSERVER = 1}
      if g_Config.boNightMareServer then
        SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 2, m_VersionManage.ServerVerSion);
{$IFEND}
      if g_Config.botimeServer then
        SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 7, 0, m_VersionManage.ServerVerSion);        //时长区
    end;

    FillChar(Rec, SizeOf(TREC) * 6, 0);
    Rec[0].n := $0A;
    Rec[1].n := $19;
    Rec[2].n := $2D;
    Rec[3].n := $4B;
    Rec[4].n := $96;
    Rec[5].n := $FA;
    m_defMsg := MakeDefaultMsg(1840, Integer(Self), 3, 0, 6);
    SendSocket(@m_defMsg, EnCodeBuffer(@Rec[0], SizeOf(TREC) * 6));

    SendDefMessage(SM_1809, 0, 0, 0, 2, '');                                                        //未知
    nCheckCode := 1;
    if m_boPneuma then begin
      SendDefMessage(SM_BAGSIZE, Integer(Self), 0, m_nBagSize, 0, '');
    end;
    nCheckCode := 2;

    SendDefMessage(1096, 0, 1, 0, 0, '');

    if not m_boPneuma then begin
      SendDefMessage(SM_PERSONALSIGN, Integer(Self), 1, 0, m_wPersonalCode, m_sPersonalSign);
      SendDefMessage(SM_PERSONALSIGN, Integer(Self), 2, 0, 0, m_sTmpRank);
    end else
      SendDefMessage(SM_TASKINFO, 0, 0, 0, 0, '');
    nCheckCode := 5;
    m_nCharStatus := GetCharStatus();
    nCheckCode := 6;
    m_nMagicStatus := GetMagicStatus();
    nCheckCode := 7;
    //发送地图信息
    m_defMsg := MakeDefaultMsg(SM_NEWMAP, Integer(Self), m_nCurrX, m_nCurrY, 10240);                // nObjCount);
    SendSocket(@m_defMsg, EnCodeString(m_PEnvir.m_MapFlag.sClientMapName));
    nCheckCode := 9;
    SendMapDescription;
    nCheckCode := 10;
    //发送名字
    SendDefMessage(SM_9609, Integer(Self), 0, 0, 0, m_sCharName);
    m_defMsg := MakeDefaultMsg(SM_USERNAME, Integer(Self), GetCharColor(Self), 0, 0);
    SendSocket(@m_defMsg, EnCodeString(GetShowName));
    nCheckCode := 11;
    //发送公告信息
    ExecuteScript(g_FunctionNPC, '@Notice');
    nCheckCode := 12;
    if not m_boSendNotice then begin
      nCheckCode := 14;
      LoadList := TStringList.Create;
      Noticeanager.GetNoticesg('Notice', LoadList);
      sNoticesg := '';
      for i := 0 to LoadList.Count - 1 do begin
        sNoticesg := sNoticesg + LoadList.Strings[i] + #$20#$1B;
      end;
      LoadList.free;
      nCheckCode := 15;
      if g_FunctionNPC <> nil then
        sNoticesg := g_FunctionNPC.GetLineVariableText(Self, sNoticesg);
      SendDefMessage(SM_SENDNOTICE, Integer(Self), 257, 38, 0, sNoticesg);

      m_boSendNotice := True;
    end;
    ExecuteScript(g_ManageNPC, '@_历_活跃_HOME');
    if (g_Config.boMagicCityServer){$IF DEMONSERVER = 1} or (g_Config.boNightMareServer){$IFEND} then begin
      ExecuteScript(g_ManageNpc, '@_活力值_MAIN');
    end;
    if g_Config.boTimeBackServer then begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 2, 0, m_VersionManage.ServerVerSion);
    end else if g_Config.boMagicCityServer then begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 0, m_VersionManage.ServerVerSion);
{$IF DEMONSERVER = 1}
    end else if g_Config.boNightMareServer then begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 5, 2, m_VersionManage.ServerVerSion);
{$IFEND}
    end else if g_Config.botimeServer then begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 256, 7, 0, m_VersionManage.ServerVerSion);      //时长区
    end else begin
      SendDefMessage(SM_SRVVERSION, Integer(Self), 0, 0, 0, m_VersionManage.ServerVerSion);
      //发送练体信息

    end;

    //发送宗族徽记
    if (m_ClanInsignia.sClanName <> '') and (m_ClanInsignia.sGuildName <> '') and (m_ClanInsignia.sInsignia <> '') then begin
      g_PacketManage3.Init;
      g_PacketManage3.WriteInteger(1);
      g_PacketManage3.WriteInteger(Integer(Self));
      g_PacketManage3.WriteString(m_ClanInsignia.sClanName, SizeOf(m_ClanInsignia.sClanName));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteString(m_ClanInsignia.sGuildName, SizeOf(m_ClanInsignia.sGuildName));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteString(m_ClanInsignia.sInsignia, SizeOf(m_ClanInsignia.sInsignia));
      g_PacketManage3.WriteByte(0);
      g_PacketManage3.WriteInteger(m_ClanInsignia.Time);
      SendDefMessage(2119, Integer(Self), 0, 0, 0, g_PacketManage3.GetMsg(), True);
    end;

    i := GetFeatureToLong(Self);
    m_defMsg := MakeDefaultMsg(SM_FEATURECHANGED, Integer(Self), LoWord(i), HiWord(i), GetGender);
    SendSocket(@m_defMsg, GetFeatureChangedMsg());
    nCheckCode := 18;
    nCode := 0;
    nType := 0;
    if not g_Config.boClassicServer then begin                                                      //修为系统

      if g_Config.boClientRedPacket then
        nCode := nCode + 32;
      if g_Config.boClientPreferential then
        nType := 8;
      if g_Config.boClientBackUserExp then
        nType := nType + 1;
      SendDefMessage(SM_816, nType, 0, MakeWord(15, nCode), 0, '');
    end else begin
      SendDefMessage(SM_816, 0, 1, 15, 0, '');
    end;

    if g_Config.boClientNewCelebration then begin
      g_PacketManage3.Init;
      g_PacketManage3.WriteInteger(1);
      g_PacketManage3.WriteInteger($0F);
      g_PacketManage3.WriteInteger(1);
      SendDefMessage(2193, Integer(Self), 0, 0, 0, g_PacketManage3.GetMsg, True);
    end;

    if g_RedPacketList.Count > 0 then begin                                                         //发送红包信息
      for I := 0 to g_RedPacketList.Count - 1 do
        SendRedPacketWindow(I);
    end;

    if not m_boPneuma then begin
      //发送任务信息
      SendTaskList;
      //发送天元心法属性
      ClientQueryMentalAbilitys(Self);
      //发送仙官信息
      SendCentsOfficerInfo();
      //元气值
      SendDefMessage(SM_VITALITY, Integer(Self), m_wVitaLity, m_Abil.wMaxVitaLity, 0, '');
      //发送宗族信息
      SendFiendList(4);

    end;
  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [nCheckCode]));
      MainOutMessage(E.Message);
    end;
  end;
end;

procedure TPlayObject.SendPetInfo(State: byte);
var
  i, nExp                               : Integer;
  PetInfo                               : TPetInfo;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  btType, btReLive                      : byte;
begin
  FillChar(PetInfo, SizeOf(TPetInfo), #0);
  case State of
    1: begin                                                                                        //刚放出
        PetInfo.nMakeIndex := m_PetInfo[0].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[0].sCharName;
        btType := m_PetInfo[0].btType;
        btReLive := m_PetInfo[0].btReLive;
        PetInfo.btLevel := m_PetInfo[0].wLevel;
      end;
    3: begin                                                                                        //摆摊
        PetInfo.nMakeIndex := m_PetInfo[1].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[1].sCharName;
        btType := m_PetInfo[1].btType;
        btReLive := m_PetInfo[1].btReLive;
        PetInfo.btLevel := m_PetInfo[1].wLevel;
      end;
    2, 6: begin                                                                                     //骑乘
        PetInfo.nMakeIndex := m_PetInfo[2].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[2].sCharName;
        btType := m_PetInfo[2].btType;
        btReLive := m_PetInfo[2].btReLive;
        PetInfo.btLevel := m_PetInfo[2].wLevel;
      end;
    7, 8: begin                                                                                     //元神骑乘
        PetInfo.nMakeIndex := m_PetInfo[3].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[3].sCharName;
        btType := m_PetInfo[3].btType;
        btReLive := m_PetInfo[3].btReLive;
        PetInfo.btLevel := m_PetInfo[3].wLevel;
      end;
    9: begin
        PetInfo.nMakeIndex := m_PetInfo[4].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[4].sCharName;
        btType := m_PetInfo[4].btType;
        btReLive := m_PetInfo[4].btReLive;
        PetInfo.btLevel := m_PetInfo[4].wLevel;
      end;
    10: begin                                                                                       //魂佑附体
        PetInfo.nMakeIndex := m_PetInfo[5].nMakeIndex;
        PetInfo.sCharName := m_PetInfo[5].sCharName;
        btType := m_PetInfo[5].btType;
        btReLive := m_PetInfo[5].btReLive;
        PetInfo.btLevel := m_PetInfo[5].wLevel;
      end;
  end;

  GetUserItemByMakeIndex(PetInfo.nMakeIndex, UserItem);
  if (UserItem <> nil) then begin
    PetInfo.wExp := UserItem.dwExp;
    PetInfo.dwVil := MakeLong(MakeWord(UserItem.btValue[0], UserItem.btValue[1]), MakeWord(UserItem.btValue[2], UserItem.btValue[3]));
    PetInfo.dwExp := UserItem.dwExp;
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem <> nil then begin
      PetInfo.btType := MakeWord(UserItem.btValue[9] + StdItem.AniCount * 8, 0);
    end;
  end;

  PetInfo.btKind := UserItem.btValue[8];
  PetInfo.bt1 := 9;
  PetInfo.dw1 := 0;
  PetInfo.btHP := 100;
  PetInfo.dw2 := 0;
  PetInfo.dw3 := 0;
  PetInfo.dw4 := 0;
  PetInfo.dw5 := 0;
  PetInfo.btState := State;                                                                         //刚放出是1,骑上是2 摆摊是3  9探宝

  if (m_Pet <> nil) then begin
    PetInfo.wHP := CalcCent(m_Pet.m_WAbil.dwHP, m_Pet.m_WAbil.dwMaxHP);
    PetInfo.wMaxHP := 100;
    PetInfo.dwMaxExp := GetPetUpExp(btReLive, PetInfo.btLevel);
  end;
  PetInfo.bt2 := 0;
  PetInfo.dw7 := 0;
  PetInfo.bt2 := 0;
  PetInfo.int64Exp := UserItem.dwExp;
  PetInfo.int64MaxExp := GetPetUpExp(btReLive, PetInfo.btLevel);

  m_defMsg := MakeDefaultMsg(34977, 0, 356, 1, 0);
  SendSocket(@m_defMsg, EnCodeBuffer(@PetInfo, SizeOf(TPetInfo)));
end;

procedure TPlayObject.SendScriptItemPic(sMsg: string; nParam: Integer);
var
  sName                                 : string;
  StdItem                               : pTStdItem;
  StdItem80                             : TStdItem;
  UserItem                              : TUserItem;
begin
  if sMsg = '' then Exit;
  sName := Trim(DeCodeString(sMsg));
  StdItem := UserEngine.GetStdItem(sName);
  if StdItem = nil then Exit;
  StdItem80 := StdItem^;

  m_defMsg := MakeDefaultMsg(CM_ITEMPIC, Integer(Self), nParam, 0, 0);
  FillChar(UserItem, SizeOf(TUserItem), #0);
  UserItem.MakeIndex := 1;
  UserItem.wIndex := UserEngine.GetStdItemIdx(sName);
  UserItem.Dura := StdItem80.DuraMax;
  UserItem.DuraMax := StdItem80.DuraMax;

  if Assigned(m_VersionManage) then
  try
    SendSocket(@m_defMsg, m_VersionManage.OnGetClientItemToMsg(Self, @UserItem));
  except
    MainOutMessage(Format('TPlayObject::OnGetClientItemToMsg SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;

end;

//发送消息到RunGate

procedure TPlayObject.SendSocket(DefMsg: pTDefaultMessage; sMsg: string);
//004CAB38
var
  MsgHdr                                : TMsgHeader;
  nSendBytes                            : Integer;
  tBuff                                 : PChar;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::SendSocket..';
  sFindMsg1                             = '玩家名字:%s,发送封包Ident:%d Recog:%d Param:%d Tag:%d Series:%d Msg:%s';
begin
  if (m_btRaceServer <> RC_PLAYOBJECT) then Exit;
  if m_nSocket = -1 then Exit;
  if m_boOfflineGetGamePoint and (DefMsg <> nil) and (DefMsg.Ident <> SM_OUTOFCONNECTION) then Exit;

  tBuff := nil;
  try
    MsgHdr.dwCode := RUNGATECODE;
    MsgHdr.nSocket := m_nSocket;
    MsgHdr.wGSocketIdx := m_nGSocketIdx;
    MsgHdr.wIdent := GM_DATA;

    if DefMsg <> nil then begin
      if sMsg <> '' then begin
        MsgHdr.nLength := Length(sMsg) + SizeOf(TDefaultMessage) + 1;
        nSendBytes := MsgHdr.nLength + SizeOf(TMsgHeader);
        GetMem(tBuff, nSendBytes + SizeOf(Integer));
        Move(nSendBytes, tBuff^, SizeOf(Integer));
        Move(MsgHdr, tBuff[SizeOf(Integer)], SizeOf(TMsgHeader));
        Move(DefMsg^, tBuff[SizeOf(TMsgHeader) + SizeOf(Integer)], SizeOf(TDefaultMessage));
        Move(sMsg[1], tBuff[SizeOf(TDefaultMessage) + SizeOf(TMsgHeader) + SizeOf(Integer)], Length(sMsg) + 1);
      end else begin
        MsgHdr.nLength := SizeOf(TDefaultMessage);
        nSendBytes := MsgHdr.nLength + SizeOf(TMsgHeader);
        GetMem(tBuff, nSendBytes + SizeOf(Integer));
        Move(nSendBytes, tBuff^, SizeOf(Integer));
        Move(MsgHdr, tBuff[SizeOf(Integer)], SizeOf(TMsgHeader));
        Move(DefMsg^, tBuff[SizeOf(TMsgHeader) + SizeOf(Integer)], SizeOf(TDefaultMessage));
      end;
    end else begin
      if sMsg <> '' then begin
        MsgHdr.nLength := -(Length(sMsg) + 1);
        nSendBytes := abs(MsgHdr.nLength) + SizeOf(TMsgHeader);
        GetMem(tBuff, nSendBytes + SizeOf(Integer));
        Move(nSendBytes, tBuff^, SizeOf(Integer));
        Move(MsgHdr, tBuff[SizeOf(Integer)], SizeOf(TMsgHeader));
        Move(sMsg[1], tBuff[SizeOf(TMsgHeader) + SizeOf(Integer)], Length(sMsg) + 1);
      end;
    end;
    if not RunSocket.AddGateBuffer(m_nGateIdx, tBuff) then begin
      FreeMem(tBuff);
    end;
  except
    MainOutMessage(sExceptionMsg);
  end;
end;

procedure TPlayObject.SendTaskList;
var
  i, m                                  : Integer;
  w                                     : word;
  TaskDesc                              : string;
  TaskTitle, Taskaim                    : string;
  pTask                                 : PTTask;
begin
  //发送任务列表
  SendDefMessage(SM_TASKINFO, 0, 0, 0, 0, Format(sTaskInfo, [m_nMaxTaskCount, m_nAchievement, m_nTaskCount]));
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.Step <= 0 then Continue;
    TaskDesc := UserEngine.GetTaskStepInfo(pTask^.TaskID, pTask^.Step, TaskTitle, Taskaim);

    TaskDesc := '{Task title=' + TaskTitle + '}' + TaskDesc + '</Task>';
    if Taskaim <> '' then
      TaskDesc := TaskDesc + '<aim>' + Taskaim + '</aim>';

    if g_FunctionNPC <> nil then
      TaskDesc := g_FunctionNPC.GetLineVariableText(Self, TaskDesc);

    m := UserEngine.GetMainTask(pTask^.TaskID);

    w := HiWord(pTask^.Step);
    if (w = 0) or (HiByte(w) = 2) then
      SendDefMessage(SM_TASKINFO, pTask^.TaskID, 0, 0, MakeWord(1, m), TaskDesc)
    else
      SendDefMessage(SM_TASKINFO, pTask^.TaskID, LoByte(w), 0, MakeWord(3, m), TaskDesc);           //刷新的五色任务
  end;
end;

procedure TPlayObject.SendTigerInfo();
var
  i, nValue, nFelement                  : Integer;
begin
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王

  if (m_TorDDM.Tiger.DB.level > 0) or (m_TorDDM.Tiger.DB.Exp > 0) then begin
    g_LargePacketManage.Init;
    g_LargePacketManage.WriteWord(m_TorDDM.Tiger.DB.level);
    g_LargePacketManage.WriteDWORD(m_TorDDM.Tiger.DB.Exp);
    g_LargePacketManage.WriteDWORD(m_TorDDM.Tiger.Abil.MaxExp);

    nValue := 0;
    nFelement := 1;
    for i := 0 to 4 do begin
      g_LargePacketManage.WriteByte(m_TorDDM.Tiger.DB.FelementAbil[i]);
      if (m_TorDDM.Tiger.DB.FelementAbil[i] > nValue) then begin
        nValue := m_TorDDM.Tiger.DB.FelementAbil[i];
        nFelement := i + 1;
      end;
    end;

    for i := 0 to 8 do begin
      g_LargePacketManage.WriteByte(m_TorDDM.Tiger.DB.SkillLevel[i]);                               //虎王的9个基本技能
    end;

    if m_TorDDM.Tiger.DB.Dragon > 0 then begin
      for i := 0 to 7 do begin
        g_LargePacketManage.WriteByte(m_TorDDM.Tiger.DB.DragonSkillLevel[i]);                       //八个龙王技能
      end;
    end;

    g_LargePacketManage.WriteByte(nFelement);
    g_LargePacketManage.WriteWord(m_TorDDM.Tiger.AddAbil.HP);
    g_LargePacketManage.WriteDWORD(m_TorDDM.Tiger.DB.ReCallTick);

    //虎王的数据
    if (m_TorDDM.Tiger.DB.Dragon = 0) then begin
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.DC);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.DC2);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.MC);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.MC2);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.AC);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.AC2);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.MAC);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.Abil.MAC2);
    end;
    g_LargePacketManage.WriteByte(m_TorDDM.Tiger.Abil.HitPoint);
    g_LargePacketManage.WriteByte(m_TorDDM.Tiger.Abil.MagicNicety);
    g_LargePacketManage.WriteByte(m_TorDDM.Tiger.Abil.SpeedPoint);
    g_LargePacketManage.WriteByte(m_TorDDM.Tiger.Abil.AntiMagic);

    if m_TorDDM.Tiger.DB.Dragon > 0 then begin
      g_LargePacketManage.WriteWord(0);
      g_LargePacketManage.WriteWord(0);                                                             //技能虚弱
      g_LargePacketManage.WriteWord(0);                                                             //技能霸体
      g_LargePacketManage.WriteWord(0);
      g_LargePacketManage.WriteWord(0);
      g_LargePacketManage.WriteWord(m_TorDDM.Tiger.AddAbil.HP);
      g_LargePacketManage.WriteWord(0);
      m_defMsg := MakeDefaultMsg(SM_DRAGONINFO, 0, 0, 0, 0);
    end else begin
      g_LargePacketManage.WriteWord(0);
      m_defMsg := MakeDefaultMsg(SM_TIGERINFO, 0, 0, 0, 0);
    end;
    SendSocket(@m_defMsg, g_LargePacketManage.GetMsg);
  end;
end;

//珍宝阁

procedure TPlayObject.SendTreasurePavilion;
var
  nCount, i, ii                         : Integer;
  G                                     : TGuild;
begin
  if m_MyGuild = nil then Exit;
  try
    G := TGuild(m_MyGuild);
    if not G.boTowerStatus then begin
      SendDefMessage(SM_TREASUREPAVILION, 0, 4, 0, 0, '通灵塔资源不足被封闭,无法开启珍宝阁。');
      Exit;
    end;
    nCount := Length(G.m_TreasurePavilion);
    if nCount > 0 then begin
      g_LargePacketManage.Init;
      for i := 0 to nCount - 1 do begin
        g_LargePacketManage.WriteBuffer(G.m_TreasurePavilion[i], 11);
        g_LargePacketManage.WriteString(G.m_TreasurePavilion[i].sUserName);
        g_LargePacketManage.WriteString(G.m_TreasurePavilion[i].sItemName);
      end;

      m_defMsg := MakeDefaultMsg(SM_TREASUREPAVILION, 0, MakeWord(0, nCount), 0, 0);
      SendSocket(@m_defMsg, g_LargePacketManage.GetMsg);
    end else
      SendDefMessage(SM_TREASUREPAVILION, 0, 0, 0, 0, '');
  except
    on E: Exception do begin
      MainOutMessage('procedure TPlayObject.SendTreasurePavilion');
      MainOutMessage(E.Message);
    end;
  end;
end;

//发送本人物所学习了的技能列表

procedure TPlayObject.SendUseMagic();
var
  i, nCount                             : Integer;
  UserMagic                             : pTUserMagic;
  ClientMagic                           : TClientMagic;
  oClientMagic                          : ToClientMagic;
  wCode                                 : word;
begin
  nCount := 0;
  wCode := $FFFF;
  g_LargePacketManage.Init;

  if m_boInosculatePneuma then begin
    //融合元神的技能
    for i := 0 to m_MagicList.Count - 1 do begin
      UserMagic := pTUserMagic(m_MagicList.Items[i]);
      if (UserMagic^.btType in [MAG_AMALGAMATION, MAG_AMALGAMATION_STUDY]) then begin
        UserMagic.GetClientMagic(@ClientMagic);
        g_LargePacketManage.WriteBuffer(ClientMagic, SizeOf(TClientMagic));
        Inc(nCount);
      end;
    end;
  end else begin
    for i := 0 to m_MagicList.Count - 1 do begin
      UserMagic := pTUserMagic(m_MagicList.Items[i]);
      if UserMagic^.btType < MAG_AMALGAMATION then begin
        UserMagic.GetClientMagic(@ClientMagic);





     if m_nSoftVersionDate < 20090402 then                                                            //1978使用
        g_LargePacketManage.WriteBuffer(ClientMagic, SizeOf(TOClientMagic)- 7)
      else

      g_LargePacketManage.WriteBuffer(ClientMagic, SizeOf(TClientMagic));

    //    MainOutMessage(Format('TPlayObject::SoftVersionDate:%d', [m_nSoftVersionDate]));
        Inc(nCount);
      end;

      if (UserMagic.GetMagIdx in [110..115, 108, 109, 120]) then begin
        if UserMagic.btKey = 0 then begin
          case UserMagic.GetMagIdx of
            120: wCode := wCode xor 1;
            108: wCode := wCode xor 2;
            109: wCode := wCode xor 4;
            110: wCode := wCode xor 8;
            111: wCode := wCode xor $10;
            112: wCode := wCode xor $20;
            113: wCode := wCode xor $40;
            114: wCode := wCode xor $80;
            115: wCode := wCode xor $100;
          end;
        end;
      end;
    end;
  end;

  if nCount > 0 then begin
    m_defMsg := MakeDefaultMsg(SM_SENDMYMAGIC, 0, 0, 0, 0);
    SendSocket(@m_defMsg, g_LargePacketManage.GetMsg);
    if m_boPneuma then begin
      if (m_PneumaObject <> nil) and (m_PneumaObject is TPlayObject) then
        TPlayObject(m_PneumaObject).ClientMagic_All_LongWenGang_List(Self);
    end else
      ClientMagic_All_LongWenGang_List(Self);
  end;

  SendDefMessage(CM_MAGICSWITCH, Integer(Self), m_nCurrX, m_nCurrY, wCode, '');
end;

procedure TPlayObject.SetScriptLabel(sLabel: string);
begin
  m_CanJmpScriptLableList.Clear;
  m_CanJmpScriptLableList.Add(sLabel);
end;

//命令  @MapInfo 地图号 X Y

procedure TPlayObject.ShowMapInfo(sMAP, sX, sY: string);
var
  Map                                   : TEnvirnoment;
  nX, nY                                : Integer;
  MapCellInfo                           : pTMapCellinfo;
begin
  nX := Str_ToInt(sX, 0);
  nY := Str_ToInt(sY, 0);
  if (sMAP <> '') and (nX >= 0) and (nY >= 0) then begin
    Map := g_MapManager.FindMap(sMAP);
    if Map <> nil then begin
      if Map.GetMapCellInfo(nX, nY, MapCellInfo) then begin
        SysMsg('标志: ' + IntToStr(MapCellInfo.chFlag), c_Green, t_Hint);
        if MapCellInfo.ObjList <> nil then begin
          SysMsg('对象数: ' + IntToStr(MapCellInfo.ObjList.Count), c_Green,
            t_Hint);
        end;
      end else begin
        SysMsg('取地图单元信息失败: ' + sMAP, c_Red, t_Hint);
      end;
    end;
  end else begin
    SysMsg('请按正确格式输入: ' + g_GameCommand.MAPINFO.sCmd +
      ' 地图号 X Y', c_Green, t_Hint);
  end;
end;

procedure TPlayObject.StartMapEventOfButch();
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfButch.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfButch.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        '*',
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;

procedure TPlayObject.StartMapEventOfDropItem(sItemName: string);
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfDropItem.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfDropItem.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        sItemName,
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;

procedure TPlayObject.StartMapEventOfMine();
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfMine.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfMine.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        '*',
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;

procedure TPlayObject.StartMapEventOfPickUpItem(sItemName: string);
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfPickUpItem.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfPickUpItem.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        sItemName,
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;

procedure TPlayObject.StartMapEventOfRun();
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfRun.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfRun.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        '*',
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;

procedure TPlayObject.StartMapEventOfWalk();
var
  i                                     : Integer;
  boGotoLabel                           : Boolean;
  MapEvent                              : pTMapEvent;
begin
  boGotoLabel := False;
  for i := 0 to g_MapEventListOfWalk.Count - 1 do begin
    MapEvent := pTMapEvent(g_MapEventListOfWalk.Items[i]);
    if MapEvent <> nil then begin
      if IsGotoLabel(MapEvent.m_sMapName,
        MapEvent.m_nCurrX,
        MapEvent.m_nCurrY,
        MapEvent.m_nRange,
        MapEvent.m_MapFlag.nQuestUnit,
        MapEvent.m_MapFlag.boOpen,
        MapEvent.m_Condition.sItemName,
        '*',
        MapEvent.m_Condition.boNeedGroup, MapEvent.m_nRandomCount) then begin
        boGotoLabel := True;
        Break;
      end;
    end;
  end;
  if boGotoLabel and (MapEvent <> nil) then begin
    case MapEvent.m_StartScript.nLable of
      0: ;
      1: begin
          ExecuteScript(g_FunctionNPC, MapEvent.m_StartScript.sLable);
        end;
    end;
  end;
end;


procedure TPlayObject.StruckDamage(nDamage: Integer);
var
  i, j                                  : Integer;
  nDam                                  : Integer;
  nDura, nOldDura                       : Integer;
  StdItem                               : pTStdItem;
  bo19                                  : Boolean;
  AddItem                               : pTUserItem;
begin
  if nDamage <= 0 then Exit;

  nDam := Random(g_Config.nDamDuraRandom) + g_Config.nDamDuraValue;

  if m_wStatusTimeArr[POISON_DAMAGEARMOR] > 0 then begin
    nDam := Round(nDam * (g_Config.nPosionDamagarmor / 10) {1.2});
  end;

  if m_boSuperMan then nDam := 0;                                                                   //无敌模式不掉持久

  bo19 := False;
  if m_UseItems[U_DRESS].wIndex > 0 then begin
    StdItem := UserEngine.GetStdItem(m_UseItems[U_DRESS].wIndex);
    if not CheckSPCode(StdItem.Reserved, RE_NODECDRUE) then begin                                   //物品控制-不掉持久
      nDura := m_UseItems[U_DRESS].Dura;
      nOldDura := Round(nDura / 1000);
      Dec(nDura, nDam);
      if nDura <= 0 then begin
        //可以控制物品破碎
        if StdItem.Broken > 0 then begin
          New(AddItem);
          AddItem^ := m_UseItems[U_DRESS];
          if AddItemToBag(AddItem) then
          begin
            SendDelItems(@m_UseItems[U_DRESS]);
            AddItem.btItemExt[4] := 4;                                                              //物品破碎
            SendUpdateItem(AddItem);
            SendAddItem(AddItem);
            SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
            SysMsg(StdItem.Name + '持久过低,已破碎,已自动放入你的包裹!', c_Pink, t_Hint);

            m_UseItems[U_DRESS].wIndex := 0;
            m_UseItems[U_DRESS].MakeIndex := 0;
            FeatureChanged();
            m_UseItems[U_DRESS].wIndex := 0;
            m_UseItems[U_DRESS].Dura := 0;

            bo19 := True;
          end else begin
            Dispose(AddItem);
          end;
        end else begin
          SendDelItems(@m_UseItems[U_DRESS]);
          if StdItem.boGameLog = 1 then
            AddGameDataLog('3' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(m_UseItems[U_DRESS].MakeIndex) + #9 +
              'TRUE' + #9 +
              '0');

          m_UseItems[U_DRESS].wIndex := 0;
          m_UseItems[U_DRESS].MakeIndex := 0;
          FeatureChanged();

          m_UseItems[U_DRESS].wIndex := 0;
          m_UseItems[U_DRESS].Dura := 0;
          bo19 := True;
        end;
      end else begin
        m_UseItems[U_DRESS].Dura := nDura;
      end;
      if nOldDura <> Round(nDura / 1000) then begin
        SendMsg(Self, RM_DURACHANGE, U_DRESS, nDura, m_UseItems[U_DRESS].DuraMax, 0, '');
      end;
    end;
  end;

  for i := Low(THumItems) to High(THumItems) do begin
    if i in [U_ABUJUK, U_SOULBEAD, U_RIDEDRESS, U_BACKORNAMENT..U_XIANDAI] then Continue;

    if (m_UseItems[i].wIndex > 0) and (Random(8) = 0) then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
      if StdItem = nil then Continue;
      if (StdItem.StdMode in [18, 29]) and (StdItem.Shape = 150) then
        Continue;                                                                                   //时间物品不掉持久

      if CheckSPCode(StdItem.Reserved, RE_NODECDRUE) then
        Continue;                                                                                   //物品控制-不掉持久

      nDura := m_UseItems[i].Dura;
      nOldDura := Round(nDura / 1000);
      Dec(nDura, nDam);
      if nDura <= 0 then begin
        if StdItem.Broken > 0 then begin
          New(AddItem);
          AddItem^ := m_UseItems[i];
          if AddItemToBag(AddItem) then
          begin
            SendDelItems(@m_UseItems[i]);
            AddItem.btItemExt[4] := 4;                                                              //物品破碎
            SendUpdateItem(AddItem);
            SendAddItem(AddItem);
            SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
            SysMsg(StdItem.Name + '持久过低,已破碎,已自动放入你的包裹!', c_Pink, t_Hint);

            m_UseItems[i].wIndex := 0;
            m_UseItems[i].MakeIndex := 0;
            FeatureChanged();
            m_UseItems[i].wIndex := 0;
            m_UseItems[i].Dura := 0;

            bo19 := True;
          end else begin
            Dispose(AddItem);
          end;
        end else begin
          SendDelItems(@m_UseItems[i]);

          if StdItem.boGameLog = 1 then
            AddGameDataLog('3' + #9 +
              m_sMapName + #9 +
              IntToStr(m_nCurrX) + #9 +
              IntToStr(m_nCurrY) + #9 +
              m_sCharName + #9 +
              StdItem.Name + #9 +
              IntToStr(m_UseItems[i].MakeIndex) + #9 +
              'TRUE' + #9 +
              '0');

          m_UseItems[i].wIndex := 0;
          m_UseItems[i].MakeIndex := 0;
          FeatureChanged();
          m_UseItems[i].wIndex := 0;
          m_UseItems[i].Dura := 0;
          bo19 := True;
        end;
      end else begin
        m_UseItems[i].Dura := nDura;
        {圣灵属性失效}
        if Round(nDura / m_UseItems[i].DuraMax) < Round(g_Config.nHolySpiritRate / 100) then begin
          if ((m_UseItems[i].btItemExt[4] and EX_HOLY) = EX_HOLY) then begin
            Dec(m_UseItems[i].btItemExt[4], EX_HOLY);
            SendUpdateItem(@m_UseItems[i]);
          end;
        end;
      end;
      if nOldDura <> Round(nDura / 1000) then begin
        SendMsg(Self, RM_DURACHANGE, i, nDura, m_UseItems[i].DuraMax, 0, '');
      end;
    end;
  end;

  if bo19 then RecalcAbilitys(True);

  //盾牌减少伤害
  if (m_btShiEldDefencePower > 0) and (g_Config.nShiEldDefenceRate > 0) then begin
    if (Random(g_Config.nShiEldDefenceRate) < 3) and (Random(g_Config.nShiEldLevelRate) < m_btShiEldDefenceLevel) then begin
      nDamage := Round(nDamage - (nDamage * m_btShiEldDefencePower / 100));
      SysMsg('恭喜你,本次盾牌成功分担部分伤害', c_Red, t_Hint);
    end;
  end;

  //圣王盾减少伤害
  if (m_btShiEldExemptHurt > 0) and (g_Config.nShiEldDefenceRate > 0) then begin
    nDamage := Round(nDamage - (nDamage * g_Config.nShiEldExemptHurt / 100));
  end;

  //金刚护体承受的伤害超过血量的120%,触发金刚净化
  if (m_wStatusTimeArr[STATE_JINGANGHUTI] > 0) and m_boRideFightOn and
    (m_MagicSkills[SKILL_JINGANGPURIFY] <> nil) and (m_MagicSkills[SKILL_42] <> nil) and (m_MagicSkills[SKILL_61] <> nil) then begin
    Inc(m_dwTotalDamage, nDamage);
    if ((m_MagicSkills[SKILL_JINGANGPURIFY].btKey = 1)) and ((m_dwTotalDamage / m_WAbil.dwMaxHP * 100) > 120) then begin
      //清除所有中毒效果
      nDam := m_PetInfo[2].wLevel + m_MagicSkills[SKILL_JINGANGPURIFY].btLevel + m_MagicSkills[SKILL_42].btLevel + m_MagicSkills[SKILL_61].btLevel;
      if (Random(g_Config.nMagJinGangPurifyRate) < nDam) then begin
        if m_wStatusTimeArr[POISON_DAMAGEARMOR] > 0 then m_wStatusTimeArr[POISON_DAMAGEARMOR] := 1;
        if m_wStatusTimeArr[POISON_DECHEALTH] > 0 then m_wStatusTimeArr[POISON_DECHEALTH] := 1;
        if m_wStatusTimeArr[POISON_DECDEFENCE] > 0 then m_wStatusTimeArr[POISON_DECDEFENCE] := 1;
        if m_wStatusTimeArr[POISON_DECMANA] > 0 then m_wStatusTimeArr[POISON_DECMANA] := 1;
        if m_wStatusTimeArr[STATE_DECHEALTH] > 0 then m_wStatusTimeArr[STATE_DECHEALTH] := 1;
        SendRefMsg(RM_510, 1, 0, 157, 0, '');
        SysMsg('金刚净化成功', c_Red, t_Hint);
        m_dwTotalDamage := 0;
        //技能经验
        TrainSkill(m_MagicSkills[SKILL_JINGANGPURIFY], Random(3) + 1, 1000);
      end;
    end;
  end;

  //火焰盾,触发抗拒火环效果
  if m_boAbilMagBubbleDefence and m_boRideFightOn and (m_MagicSkills[SKILL_FIRESHIELD] <> nil) and (m_MagicSkills[SKILL_FIRESHIELD].btKey = 1) then begin
    if (m_MagicSkills[SKILL_SHIELD] <> nil) and (m_MagicSkills[SKILL_FIREWIND] <> nil) then begin
      nDam := m_PetInfo[2].wLevel + m_MagicSkills[SKILL_FIRESHIELD].btLevel + m_MagicSkills[SKILL_SHIELD].btLevel + m_MagicSkills[SKILL_FIREWIND].btLevel;
      if (Random(g_Config.nMagFireShieldRate) < nDam) then begin
        DoSpell(m_MagicSkills[SKILL_FIRESHIELD], m_nCurrX, m_nCurrY, Self);
      end;
    end;
  end;

  //狂狮盾
  if (m_wStatusTimeArr[STATE_DEFENCEUP] > 1) and m_boRideFightOn and (m_MagicSkills[SKILL_LIONSHIELD] <> nil) and (m_MagicSkills[SKILL_LIONSHIELD].btKey = 1) then begin
    if (m_MagicSkills[SKILL_HANGMAJINBUB] <> nil) and (m_MagicSkills[SKILL_GROUPLIGHTENING] <> nil) then begin
      nDam := m_PetInfo[2].wLevel + m_MagicSkills[SKILL_LIONSHIELD].btLevel + m_MagicSkills[SKILL_HANGMAJINBUB].btLevel + m_MagicSkills[SKILL_GROUPLIGHTENING].btLevel;
      if (Random(g_Config.nMagLionShieldRate) < nDam) then begin
        DoSpell(m_MagicSkills[SKILL_GROUPLIGHTENING], m_nCurrX, m_nCurrY, Self);
        //技能经验
        TrainSkill(m_MagicSkills[SKILL_LIONSHIELD], Random(3) + 1, 1000);
      end;
    end;
  end;

  //被攻击增加元气
  if (m_btRaceServer = RC_PLAYOBJECT) and
    ((TPlayObject(Self).m_btPneumaSex > 0) or
    (TPlayObject(Self).m_Dan.SoulBaby.wKind > 0) or
    (not g_Config.boNoPneumaAddVitaLity) or
    (m_btJob = 3))
    then begin
    if (g_Config.nVitaLityAddSpeed > 0) and (nDamage > 10) then begin
      //每10点伤害,随机增加1-4点元气
      nDam := _MIN(10, (nDamage div 10) * (Random(4) + 1));
      nDam := nDam * g_Config.nVitaLityAddSpeed;

      if m_boPneuma and (m_PneumaObject <> nil) then
        m_PneumaObject.DamageVitaLity(-nDam)
      else
        DamageVitaLity(-nDam);
    end;
  end;


  DamageHealth(nDamage);
end;

function TPlayObject.SuperRepairUseItems: Boolean;
var
  i, ii                                 : Integer;
  StdItem                               : pTStdItem;
begin
  Result := False;
  ii := 0;
  for i := Low(THumItems) to High(THumItems) do begin
    if (i in [U_ABUJUK, U_SOULBEAD, U_RIDEDRESS, U_BACKORNAMENT..U_XIANDAI]) then Continue;

    if m_UseItems[i].wIndex > 0 then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
      if (StdItem = nil) then Continue;
      if CheckSPCode(StdItem.SPCode, SP_DISABLEBINQUAN) then Continue;                              //物品控制-禁止冰泉圣水
      m_UseItems[i].Dura := m_UseItems[i].DuraMax;
      SendMsg(Self, RM_DURACHANGE, i, m_UseItems[i].Dura, m_UseItems[i].DuraMax, 0, '');
      Inc(ii);
    end;
  end;

  for i := Low(m_EntopticItems) to High(m_EntopticItems) do begin
    if m_EntopticItems[i].Item.wIndex > 0 then begin
      StdItem := UserEngine.GetStdItem(m_EntopticItems[i].Item.wIndex);
      if (StdItem = nil) then Continue;
      if CheckSPCode(StdItem.SPCode, SP_DISABLEBINQUAN) then Continue;                              //物品控制-禁止冰泉圣水
      m_EntopticItems[i].Item.Dura := m_EntopticItems[i].Item.DuraMax;
      SendUpdateItem(@m_EntopticItems[i].Item);
      Inc(ii);
      //包不知道
    end;
  end;
  //融合元神穿戴的融合装备
  if m_boPneuma and m_boInosculatePneuma then begin
    for i := Low(m_TorDDM.Tiger.Items) to High(m_TorDDM.Tiger.Items) do begin
      if m_TorDDM.Tiger.Items[i].wIndex > 0 then begin
        StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[i].wIndex);
        if (StdItem = nil) then Continue;
        if CheckSPCode(StdItem.SPCode, SP_DISABLEBINQUAN) then Continue;                            //物品控制-禁止冰泉圣水
        m_TorDDM.Tiger.Items[i].Dura := m_TorDDM.Tiger.Items[i].DuraMax;
        SendUpdateItem(@m_TorDDM.Tiger.Items[i]);
        Inc(ii);
      end;
    end;
  end;

  Result := ii > 0;
  if Result then
    SysMsg(g_sSuperRepairMsg, c_Green, t_Hint);
end;

function TPlayObject.SuperRepairWeapon: Boolean;
var
  StdItem                               : pTStdItem;
begin
  Result := False;
  if m_UseItems[U_WEAPON].wIndex <= 0 then Exit;
  StdItem := UserEngine.GetStdItem(m_UseItems[U_WEAPON].wIndex);
  if StdItem = nil then Exit;
  {物品控制-禁止特殊修理}
  if CheckSPCode(StdItem.SPCode, SP_DISABLEREPAIR) then begin
    SysMsg('此物品禁止修理', c_Red, t_Hint);
    Exit;
  end;
  m_UseItems[U_WEAPON].Dura := m_UseItems[U_WEAPON].DuraMax;
  SendMsg(Self, RM_DURACHANGE, 1, m_UseItems[U_WEAPON].Dura,
    m_UseItems[U_WEAPON].DuraMax, 0, '');
  SysMsg(g_sWeaponRepairSuccess {'武器修复成功...'}, c_Green, t_Hint);
  Result := True;
end;

procedure TPlayObject.TakeItemOn(sItemName: string; btWhere: Integer);
var
  i                                     : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nOldStatus                            : Integer;
begin
  if btWhere >= MAX_HUMITEM_COUNT then Exit;

  if (sItemName = '') then begin
    if m_UseItems[btWhere].wIndex > 0 then begin                                                    //取下物品
      ClientTakeOffItems(btWhere, m_UseItems[btWhere].MakeIndex, UserEngine.GetStdItemName(m_UseItems[btWhere].wIndex));
    end;
  end else begin
    if GetUserItemByName(sItemName, UserItem) <> -1 then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if ClientTakeOnItems(btWhere, UserItem.MakeIndex, StdItem.FilterName, True) then begin
        SendDelItems(UserItem);
        SendUpdateMsg(Self, RM_SENDUSEITEMS, 0, 0, 0, 0, '');
      end;
    end;
  end;
end;

procedure TPlayObject.TigerDefendMaster(var nDamage: Integer);
var
  i, nCount                             : Integer;
  nX, nY, n18, n1C, nMapIndex           : Integer;
  wHP                                   : word;
begin
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王

  if (m_Tiger <> nil) and (not m_Tiger.m_boDeath) and (not m_Tiger.m_boGhost) then begin
    if CretInNear10XY(m_Tiger, m_nCurrX, m_nCurrY) then begin
      if (Random(g_Config.nTigerSkillRate[4]) < m_TorDDM.Tiger.DB.SkillLevel[4]) then begin
        if GetFrontPosition(nX, nY) then begin
          if GetCanMovePosition(nX, nY, 3, n18, n1C) then begin
            m_Tiger.SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
            nMapIndex := m_PEnvir.Index;
            m_Tiger.SpaceMove(m_sMapName, n18, n1C, 0, @nMapIndex);
            //恢复主人血量
            nDamage := 0;
            m_WAbil.dwHP := Round(m_WAbil.dwMaxHP / 2);
            HealthSpellChanged();
            SysMsg(Format('你的%s替你抵挡了一次致命攻击,牺牲了!', [m_Tiger.m_sCharName]), c_Red, t_Hint);
            m_Tiger.Die;
          end;
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.TigerTransferDamage(var nDamage: Integer);
var
  nObjCount, nTransfer                  : Integer;
begin
  if m_btJob = 3 then Exit;                                                                         //妖士是没有虎王
  if (m_Tiger <> nil) and (not m_Tiger.m_boDeath) and (not m_Tiger.m_boGhost) then begin
    if CretInNear10XY(m_Tiger, m_nCurrX, m_nCurrY) then begin
      if (Random(g_Config.nTigerSkillRate[3]) < m_TorDDM.Tiger.DB.SkillLevel[3]) then begin
        nObjCount := Integer(Self);
        m_Tiger.SendRefMsg(RM_510, HiWord(nObjCount), LoWord(nObjCount), 104, 0, '');
        nTransfer := Round(nDamage * (_MIN(m_TorDDM.Tiger.DB.level, 90)) / 100);
        Dec(nDamage, nTransfer);
        if nTransfer > 0 then begin
          m_Tiger.StruckDamage(nTransfer);
          m_Tiger.SendRefMsg(RM_STRUCK, 0, nTransfer, 0, Integer(Self), '');
        end;
      end;
    end;
  end;
end;

//更新人物到nStep,如果nStep=0,则在原来的基础上+1

function TPlayObject.UpdateTaskStep(const TaskID: Integer; nStep: Integer): Integer;
var
  i                                     : Integer;
  TaskTitle, TaskDesc, Taskaim          : string;
  m                                     : Integer;
  pTask                                 : PTTask;
begin
  Result := -1;
  m := 0;
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      m := pTask^.Step;
      if (nStep = 0) then nStep := LoWord(m) + 1;
      pTask^.Step := MakeLong(nStep, HiWord(m));
      ;
      Result := nStep;
      Break;
    end;
  end;

  if Result > 0 then begin
    i := UserEngine.GetMainTask(TaskID);
    if m > 0 then begin
      SendMsg(Self, RM_ADDTASK, MakeWord(2, i), TaskID, 0, 0, '');
    end;
    TaskDesc := UserEngine.GetTaskStepInfo(pTask^.TaskID, pTask^.Step, TaskTitle, Taskaim);

    TaskDesc := '{Task title=' + TaskTitle + '}' + TaskDesc + '</Task>';
    if Taskaim <> '' then
      TaskDesc := TaskDesc + '<aim>' + Taskaim + '</aim>';

    if g_FunctionNPC <> nil then
      TaskDesc := g_FunctionNPC.GetLineVariableText(Self, TaskDesc);

    SendMsg(Self, RM_ADDTASK, MakeWord(1, i), TaskID, 0, 0, TaskDesc)
  end;
end;

procedure TPlayObject.RefreshTask(const TaskID, nStep: Integer);
var
  i, m, w                               : Integer;
  TaskTitle, TaskDesc, Taskaim          : string;
  pTask                                 : PTTask;
begin
  if nStep = 0 then Exit;
  SendDefMessage(SM_TASKINFO, 0, 0, 0, 0, Format(sTaskInfo, [m_nMaxTaskCount, m_nAchievement, m_nTaskCount]));
  for i := 0 to m_TaskList.Count - 1 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      TaskDesc := UserEngine.GetTaskStepInfo(TaskID, nStep, TaskTitle, Taskaim);

      TaskDesc := '{Task title=' + TaskTitle + '}' + TaskDesc + '</Task>';
      if Taskaim <> '' then
        TaskDesc := TaskDesc + '<aim>' + Taskaim + '</aim>';

      if g_FunctionNPC <> nil then
        TaskDesc := g_FunctionNPC.GetLineVariableText(Self, TaskDesc);

      m := UserEngine.GetMainTask(TaskID);

      w := HiWord(pTask^.Step);
      if (w = 0) or (HiByte(w) = 2) then
        SendMsg(Self, RM_ADDTASK, MakeWord(1, m), TaskID, 0, 0, TaskDesc)
      else
        SendMsg(Self, RM_ADDTASK, MakeWord(3, m), TaskID, LoByte(w), 0, TaskDesc);
    end;
  end;
end;

//客户端任务ID=任务ID*100 + 任务步骤

procedure TPlayObject.ClientDelTask(const TaskID: Integer);
var
  i, m                                  : Integer;
  pTask                                 : PTTask;
begin
  if GetTaskStep(TaskID) = 0 then Exit;
  m := UserEngine.GetMainTask(TaskID);
  for i := m_TaskList.Count - 1 downto 0 do begin
    pTask := PTTask(m_TaskList[i]);
    if pTask^.TaskID = TaskID then begin
      SendMsg(Self, RM_ADDTASK, MakeWord(2, m), TaskID, 0, 0, '');
      m_sScriptParam[0] := IntToStr(pTask^.TaskID);
      m_sScriptParam[1] := IntToStr(LoWord(pTask^.Step));
      m_TaskList.Delete(i);
      Dispose(pTask);                                                                               //
      if (m = 0) then Dec(m_nTaskCount);
      ExecuteScript(g_FunctionNPC, '@CancelTask');
      Break;
    end;
  end;
end;

procedure TPlayObject.SendColorTask(const TaskID, Color: Integer);
var
  TaskTitle, TaskDesc, Taskaim          : string;
begin
  TaskDesc := UserEngine.GetTaskStepInfo(TaskID, 1, TaskTitle, Taskaim);
  TaskDesc := '{Task title=' + TaskTitle + '}' + TaskDesc + '</Task>';
  if Taskaim <> '' then
    TaskDesc := TaskDesc + '<aim>' + Taskaim + '</aim>';

  if g_FunctionNPC <> nil then
    TaskDesc := g_FunctionNPC.GetLineVariableText(Self, TaskDesc);

  SendMsg(Self, RM_ADDTASK, MakeWord(3, 1), TaskID, Color, 0, TaskDesc);
end;

procedure TPlayObject.UPGRADEMON(nType: Integer);
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  i                                     : Integer;
  nMakeIndex                            : Integer;
  tm                                    : DWORD;
  OldItem                               : TUserItem;
begin
  if (m_PetInfo[0].nMakeIndex = 0) or (m_Pet = nil) then begin
    SysMsg('请将你的灵兽处于跟随状态。', c_Red, t_Hint);
    Exit;
  end else
    nMakeIndex := m_PetInfo[0].nMakeIndex;

  {找到豹魔石}
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
      tm := DateTimeToWolTIme(Now);
      UserItem.btValue[0] := LoByte(LoWord(tm));
      UserItem.btValue[1] := HiByte(LoWord(tm));
      UserItem.btValue[2] := LoByte(HiWord(tm));
      UserItem.btValue[3] := HiByte(HiWord(tm));
      UserItem.btValue[4] := 0;                                                                     //等级
      UserItem.btValue[5] := 0;
//      UserItem.btValue[6] := 0;                                                                     //经验
//      UserItem.btValue[7] := 0;
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if nType = -1 then begin
        {灵兽转生}
        //2转到3转,属性需要重新赋值
        OldItem := UserItem^;
        UserItem.btValue[9] := _MIN(3, UserItem.btValue[9] + 1);
        UserItem.btValue[8] := _MIN(2, _Max(1, UserItem.btValue[8]));
        if (UserItem.btValue[9] = 3) then begin
          UserItem.wHP := OldItem.wHP;
          UserItem.wMP := OldItem.wMP;
          UserItem.btAntiPoison := OldItem.btAntiPoison;
          UserItem.wMAC := OldItem.wMAC;
          UserItem.btMagicNicety := OldItem.btMagicNicety;
          UserItem.btEvaDet := OldItem.btEvaDet;
          UserItem.wAC := OldItem.wAC;
          UserItem.btAntiMagic := OldItem.btAntiMagic;
          UserItem.btPoisonNicety := OldItem.btPoisonNicety;
          UserItem.btSavvy := OldItem.btSavvy;
          UserItem.btFelemEntType[0] := OldItem.btFelemEntType[0];
          UserItem.btFelemEntType[1] := OldItem.btFelemEntType[1];
          UserItem.btFelemEntPoint[0] := OldItem.btFelemEntPoint[0];
          UserItem.btFelemEntPoint[1] := OldItem.btFelemEntPoint[1];
          UserItem.wLevel := OldItem.wLevel;
          UserItem.dwExp := OldItem.dwExp;
          UserItem.wMC := OldItem.wMC;
          UserItem.wSC := OldItem.wSC;
          UserItem.wDC := OldItem.wDC;
          UserItem.btHitNicety := OldItem.btHitNicety;
          UserItem.btLuck := OldItem.btLuck;
        end;

        if (m_Pet <> nil) and (StdItem <> nil) then begin
          if (UserItem.btValue[9] = 1) then begin
            case StdItem.AniCount of
              0: m_Pet.m_wAppr := 166;
              1: m_Pet.m_wAppr := 185;
              2: m_Pet.m_wAppr := 39;
              3: m_Pet.m_wAppr := 301;
            end;
            m_Pet.SendRefMsg(RM_510, 1, 0, 84, 0, '');
          end else begin
            m_Pet.SendRefMsg(RM_510, 1, 0, 97, 0, '');
          end;
          m_Pet.m_btGender := UserItem.btValue[9];
          m_Pet.m_wSlaveExpLevel := 0;
          m_Pet.m_sCharName := _PETNAME[_MIN(10, StdItem.AniCount)][_MIN(3, UserItem.btValue[9])];
          m_Pet.RefShowName;
          m_PetInfo[0].wLevel := 0;
          m_Pet.FeatureChanged;
          m_Pet.SendRefMsg(RM_SPACEMOVE_SHOW,
            m_Pet.m_btDirection,
            m_Pet.m_nCurrX,
            m_Pet.m_nCurrY,
            0,
            m_Pet.GetShowName);
        end;
      end else begin
        {天地灵水}
        UserItem.btValue[8] := nType;
        if (m_Pet <> nil) and (StdItem <> nil) then begin
          {
           case StdItem.AniCount of
             0: m_Pet.m_wAppr := 165 + nType;
             1: m_Pet.m_wAppr := 184 + nType;
             2: m_Pet.m_wAppr := 38 + nType;
             3: m_Pet.m_wAppr := 300 + nType;
             4: ;
             5: ;
             6: ;
           end;
           }
          case nType of
            1: m_Pet.SendRefMsg(RM_510, 1, 0, 46, 0, '');
            2: m_Pet.SendRefMsg(RM_510, 1, 0, 54, 0, '');
            3: m_Pet.SendRefMsg(RM_510, 1, 0, 53, 0, '');
          end;
          m_Pet.FeatureChanged;
        end;
      end;
      SendUpdateItem(UserItem);
      PetShow(UserItem.MakeIndex);

      Break;
    end;
  end;
end;

//用户登陆游戏引擎

procedure TPlayObject.UserLogon;
var
  nUserCount                            : Integer;
  i                                     : Integer;
  ii                                    : Integer;
  UserItem                              : pTUserItem;
  UserItem1                             : pTUserItem;
  StdItem                               : pTStdItem;
  s14                                   : string;
  sItem                                 : string;
  sIPaddr                               : string;
  nOrd                                  : Integer;
  iStatus                               : Integer;
  Country                               : TCountry;
  nCode                                 : Integer;
  VoiceServ                             : TVoiceServer;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::UserLogon Name=%s Code=%d';
  sCheckIPaddrFail                      = '登录IP地址不匹配!!!';
  sClientVarMsg                         = '您当前客户端版本号为:%d';
begin
  nCode := 0;
  nUserCount := 0;
  sIPaddr := '';
  try
    if g_Config.boTestServer then begin
      if m_Abil.level < g_Config.nTestLevel then m_Abil.level := g_Config.nTestLevel;
      if m_nGold < g_Config.nTestGold then m_nGold := g_Config.nTestGold;
    end;
    if g_Config.boTestServer or (g_Config.boServiceMode) then m_nPayMent := 3;
    m_dwMapMoveTick := GetTickCount();
    m_dLogonTime := Now();
    m_dwLogonTick := GetTickCount();

    nCode := 1;
    Initialize();
    nCode := 2;
    SendMsg(Self, RM_LOGON, 0, 0, 0, 0, '');

    //等级小于7的人,在超过80人的地方将不能出生,会被随机传送
    if m_Abil.level <= 7 then begin
      if GetRangeHumanCount >= 80 then begin
        MapRandomMove(m_PEnvir.m_sMapName, 0, nil);
      end;
    end;

    if not m_boPneuma then begin
      //战斗中死亡的,也将被随机传送
      if m_boDieInFight3Zone then begin
        ii := m_PEnvir.Index;
        MapRandomMove(m_PEnvir.m_sMapName, 0, @ii);
      end;

      if m_PEnvir.m_MapFlag.boNORECONNECT then begin
        MapRandomMove(m_PEnvir.m_MapFlag.sReConnectMap, 0, nil);
      end;
    end;

    nCode := 3;
    //取用户权限
    UserEngine.GetHumPermission(m_sCharName, sIPaddr, m_btPermissionGM);

    //反盗版措施
//    if nCrackLevel = 3 then begin
//      m_nGameGold := High(LongWord);
//      m_Abil.level := High(word);
//    end;
    nCode := 4;
    GetStartPoint();
    nCode := 5;
    if m_boNewHuman then begin                                                                      //新人的处理,增加新人装备
      New(UserItem);
      if UserEngine.CopyToUserItemFromName(g_Config.sBook, UserItem) then
        //传世宝典
        m_ItemList.Add(UserItem)
      else
        Dispose(UserItem);

      New(UserItem);
      if UserEngine.CopyToUserItemFromName(g_Config.sBasicDrug, UserItem) then
        //药品
        m_ItemList.Add(UserItem)
      else
        Dispose(UserItem);

      New(UserItem);
      if m_btGender = 0 then
        sItem := g_Config.sClothsMan
      else
        sItem := g_Config.sClothsWoman;
      if UserEngine.CopyToUserItemFromName(sItem, UserItem) then                                    //衣服
        m_ItemList.Add(UserItem)
      else
        Dispose(UserItem);

      New(UserItem);
      if UserEngine.CopyToUserItemFromName(g_Config.sWoodenSword, UserItem) then
        //武器
        m_ItemList.Add(UserItem)
      else
        Dispose(UserItem);

      //新人满血
      m_Abil.dwHP := m_Abil.dwMaxHP;
      m_Abil.dwMP := m_Abil.dwMaxMP;

      //发送登陆动画
      if (m_btLastOutStatus = 0) then begin
        g_SmallPacketManage.Init;
        g_SmallPacketManage.FillWrite(10, 0);
        if not m_boNewHuman then
          g_SmallPacketManage.WriteByte(0)
        else begin
          if (g_Config.boTimeBackServer = True) then begin
            g_SmallPacketManage.WriteByte(2);
          end else if (g_Config.boMagicCityServer = True) then begin
            g_SmallPacketManage.WriteByte(3);
          end else  if (g_Config.boMagicCityServer = True) then begin
            g_SmallPacketManage.WriteByte(4);
          end else  if (g_Config.botimeServer = True) then begin
            g_SmallPacketManage.WriteByte(9);                   //时长区
          end else
          begin
            g_SmallPacketManage.WriteByte(1);
          end;
        end;

        g_SmallPacketManage.FillWrite(5, 0);

        m_defMsg := MakeDefaultMsg(1554, 0, 0, 0, 0);
        SendSocket(@m_defMsg, g_SmallPacketManage.GetMsg);
      end;
    end;

    nCode := 6;
    //检查背包中的物品是否合法
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := m_ItemList.Items[i];
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if (StdItem = nil) or IsDenyItemIndex(UserItem.MakeIndex) or
        CheckSPCode(StdItem.Reserved, RE_LOGONCLEAR) then begin                                     //非法物品编号
{$IF USESDK = DEBUG}
        SysMsg('删除非法物品:' + IntToStr(UserItem.MakeIndex), c_Pink, t_Hint);
{$IFEND}
        Dispose(UserItem);
        m_ItemList.Delete(i);
        //Dispose(UserItem);                                                    //物品控制-上线消失
      end;
    end;

    nCode := 7;
    //检查人物身上的物品是否符合使用规则
    if g_Config.boCheckUserItemPlace then begin
      for i := Low(THumItems) to High(THumItems) do begin
        if m_UseItems[i].wIndex > 0 then begin
          StdItem := UserEngine.GetStdItem(m_UseItems[i].wIndex);
          if StdItem <> nil then begin
            if IsDenyItemIndex(m_UseItems[i].MakeIndex) or (CheckSPCode(StdItem.Reserved, RE_LOGONCLEAR)) then begin //非法物品编号
              m_UseItems[i].wIndex := 0;                                                            //物品控制-上线消失
            end else if not CheckUserItems(i, StdItem) then begin
              New(UserItem);
              UserItem^ := m_UseItems[i];
              if not AddItemToBag(UserItem) then begin                                              //强行加入物品数据
                m_ItemList.Insert(0, UserItem);
              end;
              m_UseItems[i].wIndex := 0;
              {超级技能项链}
            end else if StdItem.StdMode = 18 then begin
              if CheckUserItemTimeOut(@m_UseItems[i], StdItem) then begin
                m_UseItems[i].wIndex := 0;
                SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              end;
            end
              {灵鼠神佑、金牛神佑}
            else if StdItem.StdMode = 29 then begin
              if CheckUserItemTimeOut(@m_UseItems[i], StdItem) then begin
                m_UseItems[i].wIndex := 0;
                SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              end;
            end else if (StdItem.StdMode = 6) and (StdItem.Shape = 20) then begin
              if CheckUserItemTimeOut(@m_UseItems[i], StdItem) then begin
                m_UseItems[i].wIndex := 0;
                SendDelItems(@m_UseItems[i]);
                SysMsg(Format('你的%s已经到期', [StdItem.FilterName]), c_Red, t_Hint);
              end;
            end;
          end else
            m_UseItems[i].wIndex := 0;
        end;
      end;
    end;

    nCode := 8;

    //检查背包中是否有复制品
    for i := m_ItemList.Count - 1 downto 0 do begin
      UserItem := m_ItemList.Items[i];
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem = nil then Continue;
      if StdItem = nil then begin
{$IF USESDK = DEBUG}
        SysMsg('删除非法物品:' + IntToStr(UserItem.MakeIndex), c_Pink, t_Hint);
{$IFEND}
        m_ItemList.Delete(i);
        Dispose(UserItem);
        Continue;
      end;

      s14 := StdItem.Name;
      for ii := i - 1 downto 0 do begin
        UserItem1 := m_ItemList.Items[ii];
        if (UserItem.MakeIndex = UserItem1.MakeIndex) and (UserEngine.GetStdItemName(UserItem1.wIndex) = s14) then begin
{$IF USESDK = DEBUG}
          SysMsg('删除复制品:' + IntToStr(UserItem.MakeIndex), c_Pink, t_Hint);
{$IFEND}
          m_ItemList.Delete(ii);
          Dispose(UserItem1);
          Break;
        end;
      end;
      //检查背包物品和身上装备是否有复制
      for ii := Low(THumItems) to High(THumItems) do begin
        if (m_UseItems[ii].wIndex > 0) and (UserItem.MakeIndex = m_UseItems[ii].MakeIndex) and (UserEngine.GetStdItemName(m_UseItems[ii].wIndex) = s14) then begin
{$IF USESDK = DEBUG}
          SysMsg('删除复制品:' + IntToStr(m_UseItems[ii].MakeIndex), c_Pink, t_Hint);
{$IFEND}
          m_UseItems[ii].wIndex := 0;
          Break;
        end;
      end;
    end;

    nCode := 9;
    for i := Low(m_dwStatusArrTick) to High(m_dwStatusArrTick) do begin
      if m_wStatusTimeArr[i] <> 0 then m_dwStatusArrTick[i] := GetTickCount();
    end;
    nCode := 10;
    m_nCharStatus := GetCharStatus();
    m_nMagicStatus := GetMagicStatus();
    if (m_nGold > g_Config.nHumanMaxGold * 2) and (g_Config.nHumanMaxGold > 0) then m_nGold := g_Config.nHumanMaxGold * 2;
    if m_boPneuma and (m_PneumaObject <> nil) then m_btAttatckMode := m_PneumaObject.m_btAttatckMode;

    if m_wStatusTimeArr[STATE_MAGDEFENCEUP] > 0 then
      SysMsg(Format(g_sMagDefenceUpTime, [m_wStatusTimeArr[STATE_MAGDEFENCEUP]]), c_Green, t_Client);

    if m_wStatusTimeArr[STATE_DEFENCEUP] > 0 then
      SysMsg(Format(g_sDefenceUpTime, [m_wStatusTimeArr[STATE_DEFENCEUP]]), c_Green, t_Client);

    if not m_boPneuma then begin
      if (m_nSoftVersionDate < g_Config.nSoftVersionDate) or (m_VersionManage = nil) or (m_VersionManage.SoftVersion = -1) then begin
        if not g_Config.boCanOldClientLogon then begin
          SysMsg(sClientSoftVersionError, c_Red, t_Hint);
          SysMsg(sDownLoadNewClientSoft, c_Red, t_Hint);
          SysMsg(sForceDisConnect, c_Red, t_Hint);
          m_boEmergencyClose := True;
          Exit;
        end;
      end;
      if ((m_VersionManage = nil) or (m_VersionManage.SoftVersion < MIN_CLIENT_SOFTVERSION)) and g_Config.boOldClientShowHiLevel then begin
        SysMsg(sClientSoftVersionTooOld, c_Blue, t_Hint);
        SysMsg(sDownLoadAndUseNewClient, c_Red, t_Hint);
      end;

      nCode := 11;
      case m_btAttatckMode of
        HAM_ALL: SysMsg(sAttackModeOfAll, c_Green, t_Client);                                       //[攻击模式: 全体攻击]
        HAM_PEACE: SysMsg(sAttackModeOfPeaceful, c_Green, t_Client);                                //[攻击模式: 和平攻击]
        HAM_DEAR: SysMsg(sAttackModeOfDear, c_Green, t_Client);                                     //[攻击模式: 和平攻击]
        HAM_MASTER: SysMsg(sAttackModeOfMaster, c_Green, t_Client);                                 //[攻击模式: 和平攻击]
        HAM_GROUP: SysMsg(sAttackModeOfGroup, c_Green, t_Client);                                   //[攻击模式: 编组攻击]
        HAM_GUILD: SysMsg(sAttackModeOfGuild, c_Green, t_Client);                                   //[攻击模式: 行会攻击]
        HAM_PKATTACK: SysMsg(sAttackModeOfRedWhite, c_Green, t_Client);                             //[攻击模式: 红名攻击]
{$IF COUNTRYSYSTEM = 1}
        HAM_COUNTRY: SysMsg(sAttackModeOfCountry, c_Green, t_Client);                               //[攻击模式: 国家攻击]
{$IFEND}
      end;
      SysMsg(sStartChangeAttackModeHelp, c_Green, t_Client);                                        //使用组合快捷键 CTRL-H 更改攻击...
      if (g_Config.boTestServer) and (g_Config.boOldClientShowHiLevel) then SysMsg(sStartNoticeMsg, c_Green, t_Hint); //欢迎进入本服务器进行游戏...

      if UserEngine.PlayObjectCount > g_Config.nTestUserLimit then begin
        if m_btPermissionGM < 2 then begin
          SysMsg(sOnlineUserFull1, c_Red, t_Hint);
          SysMsg(sForceDisConnect, c_Red, t_Hint);
          m_boEmergencyClose := True;
        end;
      end;
    end;
    m_nBright := 0;
    m_MyGuild := g_GuildManager.MemberOfGuild(m_sCharName);
    m_MyClan := g_GuildManager.MemberOfClan(m_sCharName);

    if m_MyGuild <> nil then begin
      m_sGuildRankName := TGuild(m_MyGuild).GetRankName(Self, m_nGuildRankNo);
      for i := 0 to TGuild(m_MyGuild).m_GuildWarList.Count - 1 do begin
        SysMsg(TGuild(m_MyGuild).m_GuildWarList.Keys[i] + ' 正在与本行会进行行会战。', c_Green, t_Hint);
      end;
    end else begin
      m_nGuildGold := 0;
      GuildGoldChanged();                                                                           //没有行会则行会银两清0
    end;
    nCode := 12;
    if not m_boPneuma then begin
      RecalcTowerAbility();
      RecalcTigerLevelAbilitys;
      SendTigerInfo;                                                                                //发送虎王数据
    end;
    nCode := 13;
    RecalcAbilitys;
    nCode := 131;
    SendMsg(Self, RM_TOWERAAILITY, 0, 0, 0, 0, '');

    SendDelayMsg(Self, RM_ABILITY, 0, 0, 0, 0, '', 1000);
    nCode := 132;
    SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
    nCode := 133;
    //    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
    nCode := 134;
    SendMsg(Self, RM_ADJUST_BONUS, 0, 0, 0, 0, '');
    nCode := 135;
    SendMsg(Self, RM_DAYCHANGING, 0, 0, 0, 0, '');
    nCode := 136;
    SendDelayMsg(Self, RM_SENDUSEITEMS, 0, 0, 0, 0, '', 1000);
    SendDelayMsg(Self, CM_QUERYBAGITEMS, 0, 0, 0, 0, '', 1000);

    nCode := 137;
    //执行登陆脚本
    if not m_boOfflineResume then begin
      ExecuteScript(g_ManageNPC, '@Initialize');
      ExecuteScript(g_ManageNPC, '@Login');
    end else begin
      ExecuteScript(g_ManageNPC, '@Resume');
    end;

    SendDelayMsg(Self, RM_GOLDCHANGED, 0, m_nGold, 0, 0, '', 1000);
    SendDelayMsg(Self, RM_GAMEGOLDCHANGED, 0, m_nGameGold, 0, 0, '', 1000);

    nCode := 138;

    if not m_boPneuma then begin
      SendDelayMsg(Self, RM_GOLDCHANGED, 1, m_nBindGold, 0, 0, '', 1000);
      SendDelayMsg(Self, RM_GOLDCHANGED, 2, m_nBindGameGold, 0, 0, '', 1000);
      SendDelayMsg(Self, RM_QUERYPETSOUL, 0, 0, 0, 0, '', 1000);
      SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 0, 0, 0, '', 1000);
      SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 5, 0, 0, '', 1000);
    end else begin
      SendUpdateDelayMsg(Self, RM_REFRESHRANK, 0, 1, 0, 0, '', 1000);
    end;

    SendUseMagic();

    nCode := 15;
    //若装备了马牌
    HorseName := '';
    m_btHorseType := 0;
    if (m_UseItems[U_RIGHTHAND].wIndex > 0) then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[U_RIGHTHAND].wIndex);
      if (StdItem <> nil) and (StdItem.StdMode = 33) then begin
        if StdItem.Shape = 0 then begin
          HorseName := UserEngine.GetHorseName(@m_UseItems[U_RIGHTHAND]);
          m_btHorseType := m_UseItems[U_RIGHTHAND].btValue[0];
        end else begin
          HorseName := StdItem.Name;
          m_btHorseType := StdItem.Shape;
        end;
        if m_btHorseType > 50 then Dec(m_btHorseType, 50);
        if m_UseItems[U_RIGHTHAND].Dura < 1000 then
          m_UseItems[U_RIGHTHAND].Dura := 0
        else
          m_UseItems[U_RIGHTHAND].Dura := m_UseItems[U_RIGHTHAND].Dura - 1000;
      end;
    end;

    if (m_btHorseType = 0) and (m_UseItems[U_CHARM].wIndex > 0) then begin
      StdItem := UserEngine.GetStdItem(m_UseItems[U_CHARM].wIndex);
      if (StdItem <> nil) and (StdItem.StdMode = 33) then begin
        if StdItem.Shape = 0 then begin
          m_btHorseType := m_UseItems[U_CHARM].btValue[0];
          HorseName := UserEngine.GetHorseName(@m_UseItems[U_CHARM]);
        end else begin
          HorseName := StdItem.Name;
          m_btHorseType := StdItem.Shape;
        end;
        if m_btHorseType > 50 then Dec(m_btHorseType, 50);
        if m_UseItems[U_CHARM].Dura < 1000 then
          m_UseItems[U_CHARM].Dura := 0
        else
          m_UseItems[U_CHARM].Dura := m_UseItems[U_CHARM].Dura - 1000;
      end;
    end;

    if Length(HorseName) > 0 then begin
      if Pos('(', HorseName) > 0 then begin
        Delete(HorseName, 1, Pos('(', HorseName));
        Delete(HorseName, Length(HorseName), 1);
      end;
      //允许骑马则生成马
      if m_PEnvir.m_MapFlag.boRideOn then begin
        m_Horse := MakeSlave(HorseName, 7, 7, 100, 24 * 60 * 60, -1);
        if m_Horse <> nil then begin
          m_Horse.TurnTo(m_btDirection);
          SendDefMessage(34977, m_Horse.m_wAppr, 612, 1, 0, '');
        end;
      end else begin
        m_Horse := nil;
        SysMsg('本地图不允许骑宠。', c_Red, t_Hint);
      end;
    end;

    m_boRideOn := False;
    m_boRideFightOn := False;
    nCode := 17;
    RefShowName();

    if (m_nPayMent = 1) then begin
      SysMsg(sYouNowIsTryPlayMode, c_Red, t_Hint);
      m_nGoldMax := g_Config.nHumanTryModeMaxGold;
      if m_Abil.level > g_Config.nTryModeLevel then begin
        SysMsg('测试状态可以使用到第 ' + IntToStr(g_Config.nTryModeLevel) + ' 级。', c_Red, t_Hint);
        SysMsg(Format('链接中断,请到以下地址获得收费相关信息。(%s)', [g_Config.sWebSite]), c_Red, t_Hint);
        m_boEmergencyClose := True;
      end;
    end;

{$IF CHECKNEWMSG = 1}
    SysMsg(Format(sClientVarMsg, [m_nSoftVersionDate]), c_Red, t_Hint);
{$IFEND}

    if (m_nPayMent = 3) and (g_Config.boOldClientShowHiLevel) and not m_boPneuma then
      SysMsg(g_sNowIsFreePlayMode {'当前服务器运行于测试模式.'}, c_Green, t_Hint);

    if g_Config.boVentureServer and (g_Config.boOldClientShowHiLevel) and not m_boPneuma then
      SysMsg('当前服务器运行于冒险模式', c_Green, t_Hint);

    if (m_MagicSkills[12] <> nil) and (not m_boUseThrusting) then begin
      m_boUseThrusting := True;
      SendSocket(nil, '+LNG');
    end;
    {
    if not m_boPneuma then begin
      if m_PEnvir.m_MapFlag.boNORECONNECT then
        MapRandomMove(m_PEnvir.m_MapFlag.sReConnectMap, 0, nil)
      else if m_PEnvir.m_MapFlag.boCanMirror then
        MapRandomMove(m_sHomeMap, 0, nil);

    end;
    }

    nCode := 18;

    if CheckDenyLogon() then Exit;                                                                  //如果人物在禁止登录列表里则直接掉线而不执行下面内容

    nCode := 19;

    if m_sDearName <> '' then CheckMarry();
    CheckMaster();                                                                                  //师徒的处理
      nCode := 191;
{$IF USESDK = WL}
{$I ..\01-SDK\Macros\EnCode_Start.inc}
    nUserCount := 3000;
    if CheckValiDate <> 9123634 then begin
      nUserCount := 3000;
      SysMsg('欢迎来到传奇世界,感谢您对本服的支持于厚爱!', c_Red, t_center);
    end else
      nUserCount := 3000;
{$I ..\01-SDK\Macros\EnCode_End.inc}
{$ELSE}
    m_btPermissionGM := 11;
    nUserCount := 10 + Random(5);
{$IFEND}
     nCode := 192;
    if UserEngine.PlayObjectCount > nUserCount then begin
      if m_btPermissionGM < 10 then begin
        SysMsg(sOnlineUserFull1, c_Red, t_Hint);
        SysMsg(sForceDisConnect, c_Red, t_Hint);
        m_boEmergencyClose := True;
      end;
    end;
     nCode := 193;
    if not m_boPneuma then
   //   SendDefMessage(SM_SYSMESSAGE, 0, 0, 0, $300, '本服务器为纯公益免费服务器');
    m_dwNextBannerNoticeTime := GetTickCount + g_Config.dwHideBannerNoticeTime;
    FeatureChanged;
     nCode := 194;
    //元神组队与行会 获取本体数据
    if m_boPneuma and (m_PneumaObject <> nil) then begin
      m_btAttatckMode := m_PneumaObject.m_btAttatckMode;
      m_MyGuild := m_PneumaObject.m_MyGuild;
      m_GroupOwner := m_PneumaObject.m_GroupOwner;
      nCode := 195;

    end;

    //重置泡点方面计时
    m_dwIncGamePointTick := GetTickCount();
    m_dwIncGameGoldTick := GetTickCount();
    m_dwAutoGetExpTick := GetTickCount();

    //发送我的封号
    if (m_wExtraLevel > 0) then
      SendMsg(Self, RM_FENGHAO, MakeWord(8, LoByte(m_wExtraLevel)), GetPneumaAmbit, HiByte(m_wExtraLevel), 0, GetExtraLevelName);
     nCode := 196;
    SendMsg(Self, RM_SENDFRIENDLIST, 0, 0, 0, 0, '');
    nCode := 23;

    if m_boArrow and (g_FunctionNPC <> nil) then begin
      MainOutMessage('带宝盒上线:' + m_sCharName);
      //宝盒系统控制-带宝盒上线
    end;
    nCode := 24;
    {    if m_wAttachePoint > 0 then
          SysMsg(Format('您当前武馆积分:%d,排名第 %d 位', [m_wAttachePoint, nOrd]), c_Green, t_Hint);
        nCode := 25;
        }
    {国战系统}
{$IF COUNTRYSYSTEM = 1}
    if not m_boPneuma and (m_btCountry > 0) then begin
      if (m_PEnvir.m_btCountry > 0) and (m_btCountry <> m_PEnvir.m_btCountry) then
        SysMsg('警告:你现在进入的是外国领地!', c_Red, t_center);
      Country := GetCountryInfo(m_btCountry);
      if m_sCharName = Country.sKing then begin
        UserEngine.SendBroadCastMsg('举国上下热烈欢呼' + Country.sName + '国王' + m_sCharName + '上线了!', t_center, 0, m_btCountry);
      end;
    end;
{$IFEND}

  except
    on E: Exception do begin
      MainOutMessage(Format(sExceptionMsg, [m_sCharName, nCode]));
      MainOutMessage(E.Message);
    end;
  end;

  if not m_boPneuma and (m_nBonusPoint > 0) then
    SysMsg('你现在有' + IntToStr(m_nBonusPoint) + '点未分配的属性点', c_Blue, t_Hint);
  //新春灯笼效果
  SendDefMessage(1296, 0, byte(g_Config.boClientJoyousScene), 0, 0, '');
  SendDefMessage(808, 1, 0, 0, 0, '');                                                              //未知消息
  //发送包裹大小
  SendDefMessage(SM_BAGSIZE, Integer(Self), 0, m_nBagSize, 0, '');

  //商城积分
  if m_nCollectPoint > 0 then
    SendDefMessage(SM_COLLECTPOINT, m_nCollectPoint, 0, 0, 0, '');



  //纹佩精华值
  SendWenPeiJH();
  //人物成就信息
  ClientAchievementSystem(True);

  //妖士妖丹信息
  SendDemonDanInfo();
  //刷新一下星宿信息
  RefreshConstellation();
  //妖士星宿信息
  SendConstellationInfo();
  //妖士星宿点亮等级
  SendConstellationStarLv();
  //发送源力
  SendGemSource();

  //
  RecalcGemSacredDam();
    //SendDefMessage(2129, Integer(Self), 0, 0, 0, '');                             //显示我的战队界面

  SendDefMessage(1650, 0, HexToInt('$' + m_MagicOrder), 220, 0, '');                                //发送铁血技能
  SendDefMessage(2403, Integer(m_boComboMagic), 0, 0, 0, '');

  ClientMilitaryRank();                                                                             //军衔属性信息
  g_PacketManage6.Init;
  g_PacketManage6.WriteInteger(0);
  g_PacketManage6.WriteInteger(500);
  g_PacketManage6.FillWrite(8, 0);
  SendDefMessage(2194, Integer(Self), 0, 0, 0, g_PacketManage6.GetMsg, True);                       //显示军衔系统界面

//  g_PacketManage3.Init;
//  g_PacketManage3.WriteInteger(1);
//  g_PacketManage3.WriteInteger($0F);
//  g_PacketManage3.WriteInteger(1);
//  SendDefMessage(2193, Integer(Self), 0, 0, 0, g_PacketManage3.GetMsg, True);

  //发送神兵神力值
  if (m_UseItems[U_DRESS].wIndex > 0) and m_UseItems[U_DRESS].IsGod() then
    SendDelayMsg(Self, RM_SENDGODUSEVAL, 1, m_UseItems[U_DRESS].btValue[15], 0, 0, '', 2000);
  if (m_UseItems[U_WEAPON].wIndex > 0) and m_UseItems[U_WEAPON].IsGod() then begin
    if m_UseItems[U_WEAPON].btItemExt[20] >= 100 then begin
      Dec(m_UseItems[U_WEAPON].btItemExt[20], _Max(m_UseItems[U_WEAPON].btValue[19], 1));
    end;
    m_UseItems[U_WEAPON].btValue[15] := 0;
    m_UseItems[U_WEAPON].btValue[17] := 0;
    SendDelayMsg(Self, RM_SENDGODUSEVAL, 0, m_UseItems[U_WEAPON].btItemExt[20], 0, 0, '', 2000);
  end;

  if not m_boPneuma then begin
    //发送语聊服务器
//    FillChar(VoiceServ, SizeOf(TVoiceServer), 0);
//    VoiceServ.dw1 := $0F113701;
//    VoiceServ.dw2 := $00FA2904;
//    VoiceServ.W1 := 0;
//    VoiceServ.b1 := 0;
//    VoiceServ.Port := 7410;
//    VoiceServ.IP := '61.129.46.40';
//    m_defMsg := MakeDefaultMsg(3032, 0, 0, 0, 30);
//    SendSocket(@m_defMsg, EnCodeBuffer(@VoiceServ, SizeOf(TVoiceServer)));
    //快捷消费栏
    SendDefMessage(SM_SENDINGOTGOODSLIST, 0, 27, 2, 0, UserEngine.GetFastSellItems);
  end;

  //更新一下人物最后登陆时间
  g_PacketManage5.Init();
  g_PacketManage5.AsDWORD := m_dwDBIndex;

  FrontEngine.SendGameWorkMsg(WK_LastLogonDate, 0, g_PacketManage5.GetMsg(), False, True);
end;

function TPlayObject.UseStdmodeFunItem(StdItem: pTStdItem; boNew: Boolean = False): Boolean;
begin
  Result := False;
  if (g_FunctionNPC <> nil) and (StdItem.AniCount > 0) then begin
    if boNew then
      Result := ExecuteScript(g_FunctionNPC, '@NewStdModeFunc' + IntToStr(StdItem.AniCount))
    else
      Result := ExecuteScript(g_FunctionNPC, '@StdModeFunc' + IntToStr(StdItem.AniCount));
  end;
end;

//使用祝福油

function TPlayObject.WeaptonMakeLuck: Boolean;                                                      //004BD4A0
var
  StdItem                               : pTStdItem;
  nRand                                 : Integer;
  boMakeLuck                            : Boolean;
  UserItem                              : pTUserItem;
begin
  Result := False;
  if m_boPneuma and m_boInosculatePneuma then
    UserItem := @m_TorDDM.Tiger.Items[U_WEAPON]
  else
    UserItem := @m_UseItems[U_WEAPON];

  if UserItem.wIndex <= 0 then Exit;

  nRand := 0;
  StdItem := UserEngine.GetStdItem(UserItem.wIndex);
  if StdItem <> nil then begin
    nRand := abs((HiWord(StdItem.DC) - LoWord(StdItem.DC))) div 5;
  end;
  if Random(g_Config.nWeaponMakeUnLuckRate {20}) = 1 then begin
    MakeWeaponUnlock();
  end else begin                                                                                    //004BD527
    boMakeLuck := False;
    if UserItem.btValue[8] > 0 then begin
      Dec(UserItem.btValue[8]);
      SysMsg(g_sWeaptonMakeLuck {'武器被加幸运了...'}, c_Green, t_Hint);
      boMakeLuck := True;
    end else if UserItem.btValue[6] < g_Config.nWeaponMakeLuckPoint1
      {1}then begin
      Inc(UserItem.btValue[6]);
      SysMsg(g_sWeaptonMakeLuck {'武器被加幸运了...'}, c_Green, t_Hint);
      boMakeLuck := True;
    end else if (UserItem.btValue[6] < g_Config.nWeaponMakeLuckPoint2
      {3}) and (Random(nRand + g_Config.nWeaponMakeLuckPoint2Rate {6}) = 1) then begin
      Inc(UserItem.btValue[6]);
      SysMsg(g_sWeaptonMakeLuck {'武器被加幸运了...'}, c_Green, t_Hint);
      boMakeLuck := True;
    end else if (UserItem.btValue[6] < g_Config.nWeaponMakeLuckPoint3
      {7}) and (Random(nRand * g_Config.nWeaponMakeLuckPoint3Rate {10 + 30}) = 1) then begin
      Inc(UserItem.btValue[6]);
      SysMsg(g_sWeaptonMakeLuck {'武器被加幸运了...'}, c_Green, t_Hint);
      boMakeLuck := True;
    end;
    if m_btRaceServer = RC_PLAYOBJECT then begin
      RecalcAbilitys();
      SendUpdateItem(UserItem);
      SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
      SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
    end;
    if not boMakeLuck then
      SysMsg(g_sWeaptonNotMakeLuck {'无效'}, c_Green, t_Hint);
  end;
  Result := True;
end;
//解除武器被诅咒点数

procedure TPlayObject.MakeWeaponUnlock;
var
  UserItem                              : pTUserItem;
begin
  if m_boPneuma and m_boInosculatePneuma then
    UserItem := @m_TorDDM.Tiger.Items[U_WEAPON]
  else
    UserItem := @m_UseItems[U_WEAPON];

  if UserItem.wIndex <= 0 then Exit;

  if UserItem.btValue[6] > 0 then begin
    Dec(UserItem.btValue[6]);
    if m_btRaceServer = RC_PLAYOBJECT then
      SysMsg(g_sTheWeaponIsCursed, c_Pink, t_Hint);                                                 //你的武器被诅咒了!!!
  end else begin
    if UserItem.btValue[8] < 10 then begin
      Inc(UserItem.btValue[8]);
      if m_btRaceServer = RC_PLAYOBJECT then
        SysMsg(g_sTheWeaponIsCursed, c_Pink, t_Hint);
    end;
  end;
  if m_btRaceServer = RC_PLAYOBJECT then begin
    TPlayObject(Self).SendUpdateItem(UserItem);
    RecalcAbilitys();
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  end;
end;
//发送私聊

procedure TPlayObject.Whisper(whostr, saystr: string; nType: Integer = 1);
var
  PlayObject                            : TPlayObject;
  svidx                                 : Integer;
begin
  PlayObject := UserEngine.GetPlayObject(whostr);
  if PlayObject <> nil then begin
    if not PlayObject.m_boReadyRun then begin
      SysMsg(whostr + g_sCanotSendmsg {'无法发送信息.'}, c_Red, t_Hint);
      Exit;
    end;
    if not PlayObject.m_boHearWhisper or PlayObject.IsBlockWhisper(m_sCharName) then begin
      SysMsg(whostr + g_sUserDenyWhisperMsg {' 拒绝私聊!!!'}, c_Red,
        t_Hint);
      Exit;
    end;
    if m_btPermissionGM > 0 then begin
      PlayObject.SendMsg(PlayObject, RM_WHISPER, nType,
        g_Config.btGMWhisperMsgFColor, g_Config.btGMWhisperMsgBColor, 0,
        m_sCharName + '=> ' + saystr);
      //取得私聊信息
      if (m_GetWhisperHuman <> nil) and (not m_GetWhisperHuman.m_boGhost) then
        m_GetWhisperHuman.SendMsg(m_GetWhisperHuman, RM_WHISPER, nType,
          g_Config.btGMWhisperMsgFColor, g_Config.btGMWhisperMsgBColor, 0,
          m_sCharName + '=>' + PlayObject.m_sCharName + ' ' + saystr);

      if (PlayObject.m_GetWhisperHuman <> nil) and (not
        PlayObject.m_GetWhisperHuman.m_boGhost) then
        PlayObject.m_GetWhisperHuman.SendMsg(PlayObject.m_GetWhisperHuman,
          RM_WHISPER, nType, g_Config.btGMWhisperMsgFColor,
          g_Config.btGMWhisperMsgBColor, 0, m_sCharName + '=>' +
          PlayObject.m_sCharName + ' ' + saystr);
    end else begin
      PlayObject.SendMsg(PlayObject, RM_WHISPER, nType,
        g_Config.btWhisperMsgFColor, g_Config.btWhisperMsgBColor, 0, m_sCharName +
        '=> ' + saystr);
      if (m_GetWhisperHuman <> nil) and (not m_GetWhisperHuman.m_boGhost) then
        m_GetWhisperHuman.SendMsg(m_GetWhisperHuman, RM_WHISPER, nType,
          g_Config.btWhisperMsgFColor, g_Config.btWhisperMsgBColor, 0, m_sCharName
          + '=>' + PlayObject.m_sCharName + ' ' + saystr);

      if (PlayObject.m_GetWhisperHuman <> nil) and (not
        PlayObject.m_GetWhisperHuman.m_boGhost) then
        PlayObject.m_GetWhisperHuman.SendMsg(PlayObject.m_GetWhisperHuman,
          RM_WHISPER, nType, g_Config.btWhisperMsgFColor,
          g_Config.btWhisperMsgBColor, 0, m_sCharName + '=>' +
          PlayObject.m_sCharName + ' ' + saystr);
    end;
    //脱机泡点自动回复
    if not m_boOfflineGetGamePoint and PlayObject.m_boOfflineGetGamePoint and (PlayObject.m_sAutoSayMsg <> '') then
      PlayObject.Whisper(m_sCharName, PlayObject.m_sAutoSayMsg);
  end else begin
    if UserEngine.FindOtherServerUser(whostr, svidx) then begin
      UserEngine.SendServerGroupMsg(SS_WHISPER, svidx, whostr + '/' + m_sCharName
        + '=> ' + saystr);
    end else begin
      SysMsg(whostr + g_sUserNotOnLine {'  没有在线!!!'}, c_Red,
        t_Hint);
    end;
  end;
end;

//计算经验值,根据杀怪倍数等参数计算

procedure TPlayObject.WinExp(nExp: UInt64; nMilitaryExp: UInt64; nRepressDemonExp: UInt64);
var
  i, nLevelInt                          : Integer;
  btWhere, nC, nMilitaryExpRate         : Integer;
  StdItem                               : pTStdItem;
begin
  {杀怪增加镇魔值}
  if (g_Config.boKillMonAddAntiEvilPower) then begin
    if Random(g_Config.nAddAntiEvilPowerRate {10}) = 0 then begin
      btWhere := Random(12);
      if (m_UseItems[btWhere].wIndex > 0) and (m_UseItems[btWhere].Evil.MakeIndex <> 0) and (m_UseItems[btWhere].Evil.sName <> '') then begin
        nC := _MIN(g_Config.nAddAntiEvilPowerMax, GetRandom(g_Config.nAddAntiEvilPowerMin, g_Config.nAddAntiEvilPowerMax) + g_Config.nAddAntiEvilPowerRange);
        Inc(m_UseItems[btWhere].Evil.wPower, nC * 1000);
        SendDefMessage(SM_ANTIEVILPOWER, m_UseItems[btWhere].MakeIndex, m_UseItems[btWhere].Evil.wPower, btWhere, 0, '');
        StdItem := UserEngine.GetStdItem(m_UseItems[btWhere].wIndex);
        if StdItem <> nil then
          SysMsg(Format('你的%s获得了%d点镇魔值!!!', [StdItem.FilterName, nC div 1000]), c_Red, t_Hint);
      end;
    end;
  end;

  if (m_wFushen = 4) then begin                                                                     //神佑
    if Random(100) < g_Config.nFushen4Rate then begin
      nExp := _MININT64(MAX_ULONG64, nExp * 2);
      SysMsg('神佑成功,这次你获得了更多的经验。', c_Red, t_Hint);
    end;
  end;

  //学习了战神战魂真悟,将有概率获得双倍经验
  if (m_MagicSkills[58] <> nil) then begin
    if Random(g_Config.nMagWarrSkillWinExpRate) <= m_MagicSkills[58].btLevel * 3 + 4 then begin
      nExp := _MININT64(MAX_ULONG64, nExp * 2);
      SysMsg('凭着对战魂的领悟,这次你获得了更多的经验。', c_Red, t_Hint);
      TrainSkill(m_MagicSkills[58], Random(3) + 1, 1000);
    end;
  end;

  //学习了法之魄,将有概率获得双倍经验
  if (m_MagicSkills[68] <> nil) then begin
    if Random(g_Config.nMagWarrSkillWinExpRate) <= m_MagicSkills[68].btLevel * 3 + 4 then begin
      nExp := _MININT64(MAX_ULONG64, nExp * 2);
      SysMsg('凭着对魔法本质的认识,这次你获得了更多的经验。', c_Red, t_Hint);
      TrainSkill(m_MagicSkills[68], Random(3) + 1, 1000);
    end;
  end;

  //学习了道心清明,将有概率获得双倍经验
  if (m_MagicSkills[63] <> nil) then begin
    if Random(g_Config.nMagWarrSkillWinExpRate) <= m_MagicSkills[63].btLevel * 3 + 4 then begin
      nExp := _MININT64(MAX_ULONG64, nExp * 2);
      SysMsg('道的信念使你在杀戮中还保持着清醒,这次你获得了更多的经验。', c_Red, t_Hint);
      TrainSkill(m_MagicSkills[63], Random(3) + 1, 1000);
    end;
  end;

  //妖魂
  if (m_btJob = 3) then begin
    i := m_TorDDM.PelletSkill[13];
    if (i in [1..8]) then begin
      nExp := nExp + Round((g_PelletSkill[13].btLv[i].btVal[2] / 100) * nExp);
      SysMsg('你触发了妖魂效果', c_Red, t_Hint);
    end;
  end;
  //计算统指定杀怪功勋值倍数
  if (nMilitaryExp > 0) and (m_PneumaObject <> nil) and (g_Config.boOpenMilitaryExpShare) then
    nMilitaryExp := Round((g_Config.nMilitaryExpShare / 100) * nMilitaryExp);

  //人物指定的杀怪功勋值倍数
  if (m_dwKillMonExpLoitRateTime > 0) and (nMilitaryExp > 0) then
    nMilitaryExp := Round((m_nKillMonExpLoitRate / 100) * nMilitaryExp);

  //计算统指定杀怪镇魔珠经验倍数
  if (nRepressDemonExp > 0) and (m_PneumaObject <> nil) and (TPlayObject(m_PneumaObject).m_RepressDemon.nLevel > 0) and
    (g_Config.boOpenRepressDemonExpShare) then
    nRepressDemonExp := Round((g_Config.nRepressDemonExpShare / 100) * nRepressDemonExp);

  //人物指定的杀怪镇魔珠经验倍数
  if (m_RepressDemon.nLevel > 0) and (m_dwKillMonRepressDemonRateTime > 0) and (nRepressDemonExp > 0) then
    nRepressDemonExp := Round((m_nKillMonRepressDemonRate / 100) * nRepressDemonExp);

  //系统指定杀怪经验倍数
  nExp := g_Config.dwKillMonExpMultiple * nExp;

  //人物指定的杀怪经验倍数
  if not m_PEnvir.m_MapFlag.boNoExpRate then begin
    nExp := Round((m_nKillMonExpRate / 100) * nExp);
    nExp := Round((m_wKillMonExpRate / 100) * nExp);
  end;

  //地图上指定杀怪经验倍数
  if m_PEnvir.m_MapFlag.boEXPRATE then
    nExp := Round((m_PEnvir.m_MapFlag.nEXPRATE / 100) * nExp);

  //物品经验倍数
  if m_boExpItem then begin
    nExp := Round(m_rExpItem * nExp);
  end;
  {
    for i := Low(g_Config.LimitLevelExp) to High(g_Config.LimitLevelExp) do begin
      if g_Config.LimitLevelExp[i].nHumLevel <= 0 then
        Break;
      if m_Abil.Level = g_Config.LimitLevelExp[i].nHumLevel then begin
        dwExp := Round((g_Config.LimitLevelExp[i].nEXPRATE / 100) * dwExp);
        Break;
      end;
    end;
    }
    //人物等级杀怪经验倍数
  nExp := Round((m_WAbil.wZazen2ExpRate / 100) * nExp);
  GetExp(nExp, nMilitaryExp, nRepressDemonExp, False, g_Config.boOpenMilitaryExpShare, g_Config.boOpenRepressDemonExpShare);
end;

function TPlayObject.WinLottery: Boolean;
var
  nGold, nWinLevel, nRate               : Integer;
begin
  nGold := 0;
  nWinLevel := 0;

  nRate := Random(g_Config.nWinLotteryRate);
  if nRate in [g_Config.nWinLottery6Min..g_Config.nWinLottery6Max] then begin
    if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
      nGold := g_Config.nWinLottery6Gold;
      nWinLevel := 6;
      Inc(g_Config.nWinLotteryLevel6);
    end;
  end else
    if nRate in [g_Config.nWinLottery5Min..g_Config.nWinLottery5Max] then begin
      if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
        nGold := g_Config.nWinLottery5Gold;
        nWinLevel := 5;
        Inc(g_Config.nWinLotteryLevel5);
      end;
    end else
      if nRate in [g_Config.nWinLottery4Min..g_Config.nWinLottery4Max] then begin
        if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
          nGold := g_Config.nWinLottery4Gold;
          nWinLevel := 4;
          Inc(g_Config.nWinLotteryLevel4);
        end;
      end else
        if nRate in [g_Config.nWinLottery3Min..g_Config.nWinLottery3Max] then begin
          if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
            nGold := g_Config.nWinLottery3Gold;
            nWinLevel := 3;
            Inc(g_Config.nWinLotteryLevel3);
          end;
        end else
          if nRate in [g_Config.nWinLottery2Min..g_Config.nWinLottery2Max] then begin
            if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
              nGold := g_Config.nWinLottery2Gold;
              nWinLevel := 2;
              Inc(g_Config.nWinLotteryLevel2);
            end;
          end else
            if nRate in [g_Config.nWinLottery1Min + g_Config.nWinLottery1Max] then begin
              if g_Config.nWinLotteryCount < g_Config.nNoWinLotteryCount then begin
                nGold := g_Config.nWinLottery1Gold;
                nWinLevel := 1;
                Inc(g_Config.nWinLotteryLevel1);
              end;
            end;
  if nGold > 0 then begin
    case nWinLevel of                                                                               //
      1: SysMsg(g_sWinLottery1Msg {'祝贺您,中了一等奖。'}, c_Green,
          t_Hint);
      2: SysMsg(g_sWinLottery2Msg {'祝贺您,中了二等奖。'}, c_Green,
          t_Hint);
      3: SysMsg(g_sWinLottery3Msg {'祝贺您,中了三等奖。'}, c_Green,
          t_Hint);
      4: SysMsg(g_sWinLottery4Msg {'祝贺您,中了四等奖。'}, c_Green,
          t_Hint);
      5: SysMsg(g_sWinLottery5Msg {'祝贺您,中了五等奖。'}, c_Green,
          t_Hint);
      6: SysMsg(g_sWinLottery6Msg {'祝贺您,中了六等奖。'}, c_Green,
          t_Hint);
    end;
    if IncGold(nGold) then begin
      GoldChanged();
    end else begin
      DropGoldDown(nGold, True, nil, nil);
    end;

  end else begin
    Inc(g_Config.nNoWinLotteryCount, 500);
    SysMsg(g_sNotWinLotteryMsg {'等下次机会吧!!!'}, c_Red, t_Hint);
  end;
  Result := True;
end;

function TPlayObject.ClientTakeOnEntopticItems(btWhere: byte; nItemIdx: Integer): Boolean;
var
  i, n14, n18                           : Integer;
  UserItem, TakeoffItem                 : pTUserItem;
  StdItem, StdItem20                    : pTStdItem;
  StdItem58                             : TStdItem;
  boCanTakeOn                           : Boolean;
label
  FailExit;
begin
  StdItem := nil;
  UserItem := nil;
  Result := False;
  n14 := -1;

  if m_boPneuma then begin
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];                                                              //包裹里的物品
      if (UserItem <> nil) and (UserItem.MakeIndex = nItemIdx) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        n14 := i;
        Break;
      end;
      UserItem := nil;
    end;
  end;

  n18 := 0;
  if (StdItem <> nil) and (UserItem <> nil) then begin
    if CheckUserItems(btWhere + U_ENTOPTIC_HEND, StdItem) then begin
      //物品控制-禁止元神、红名、本体穿戴
      if m_boPneuma then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEPNEUMATAKEON))
      else if (PKLevel > 2) then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEREDTAKEON))
      else
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEHUMANTAKEON));

      if not boCanTakeOn then begin
        SysMsg('你不能佩戴此物品。', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;

      StdItem58 := StdItem^;
      ItemUnit.GetItemAddValue(UserItem, StdItem58);
      if (n18 = 0) and CheckTakeOnItems(btWhere + U_ENTOPTIC_HEND, StdItem58) and CheckItemBindUse(UserItem) then begin
        TakeoffItem := nil;
        if btWhere in [0..MAX_ENTOPTICPLACE - 1] then begin
          //取下物品
          if m_EntopticItems[btWhere].Item.wIndex > 0 then begin                                    //当前位置已装备了物品,则取下
            StdItem20 := UserEngine.GetStdItem(m_EntopticItems[btWhere].Item.wIndex);
            if (StdItem20 <> nil) then begin
              if not m_boUserUnLockDurg and ((StdItem20.Reserved and 2) <> 0) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;                                                                                  //004DAE78
              if (StdItem20.Reserved and 4) <> 0 then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
              //物品控制-禁止取下物品
              if CheckSPCode(StdItem20.SPCode, SP_DISABLETAKEOFF) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
            end;

            New(TakeoffItem);
            TakeoffItem^ := m_EntopticItems[btWhere].Item;
          end;

          m_EntopticItems[btWhere].Item := UserItem^;

          DelBagItem(n14);
          if TakeoffItem <> nil then begin
            AddItemToBag(TakeoffItem);
            SendAddItem(TakeoffItem);
          end;

          n18 := 1;
          SendDefMessage(SM_TAKEON_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');
          Result := True;

          RecalcAbilitys();
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
          SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

          // m_nCharStatus := GetCharStatus();
          // SendMsg(Self,RM_CHARSTATUSCHANGED, m_nHitSpeed, m_nCharStatus, 0, 0, '');

          FeatureChanged();
        end;
      end else n18 := -1;
    end else n18 := -1;
  end;
  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEON_FAIL, n18, 0, 0, 0, '');
end;

function TPlayObject.ClientTakeOffEntopticItems(btWhere: byte; nItemIdx: Integer): Boolean;
var
  N10, i                                : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  sName                                 : string;
  nCheckCode                            : Integer;
label
  FailExit;
begin
  N10 := 0;
  nCheckCode := 0;
  if m_boPneuma then begin
    if not m_boDealing and (btWhere in [0..MAX_ENTOPTICPLACE - 1]) then begin
      if m_EntopticItems[btWhere].Item.wIndex > 0 then begin
        if m_EntopticItems[btWhere].Item.MakeIndex = nItemIdx then begin
          StdItem := UserEngine.GetStdItem(m_EntopticItems[btWhere].Item.wIndex);
          if (StdItem <> nil) then begin
            //物品控制-禁止取下物品
            if CheckSPCode(StdItem.SPCode, SP_DISABLETAKEOFF) then begin
              SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
              N10 := -4;
              goto FailExit;
            end;

            New(UserItem);
            UserItem^ := m_EntopticItems[btWhere].Item;
            if AddItemToBag(UserItem) then begin
              m_EntopticItems[btWhere].Item.wIndex := 0;

              SendAddItem(UserItem);
              SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');

              RecalcAbilitys();
              SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
              SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

              // m_nCharStatus := GetCharStatus();
              // SendMsg(Self,RM_CHARSTATUSCHANGED, m_nHitSpeed, m_nCharStatus, 0, 0, '');

              FeatureChanged();
            end else begin
              Dispose(UserItem);
              N10 := -3;
            end;
          end;
        end;
      end else N10 := -2;
    end else N10 := -1;
  end else N10 := -4;

  FailExit:
  if N10 <= 0 then
    SendDefMessage(SM_TAKEOFF_FAIL, N10, 0, 0, 0, '');
end;


//点亮心命点

function TPlayObject.ClientIllumeHeartPoint(btWhere, btPlace: byte): Boolean;
//取魂骨级别
  function GetFetchBoneLevel(Shape: byte): byte;
  begin
    Result := 0;
    if Shape in [1..7] then Result := 1
    else if Shape in [8..14] then Result := 2
    else if Shape in [15..21] then Result := 3
    else if Shape in [22..28] then Result := 4;
  end;
  //取目标位置需要级别
  function GetPlaceLevel(): byte;
  begin
    Result := $FF;
    if btPlace in [0..1] then Result := 1
    else if btPlace in [2..4] then Result := 2
    else if btPlace in [5..8] then Result := 3
    else if btPlace in [9..13] then Result := 4;
  end;

var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  i, w                                  : Integer;
  btKismet                              : byte;
  btError                               : byte;
resourcestring
  sItemName                             = '启心石';
  sExceptionMsg1                        = '请在元神的包裹中放入启心石,才能激活或者改变心命点的属性。';
  sExceptionMsg2                        = '魂骨级别不够,无法点亮';
  sExceptionMsg3                        = '激活或者改变心命点的属性失败.';
  sGameLogMsg                           = '激活或者改变心命点的属性';
begin
  UserItem := nil;
  Result := False;
  btError := 0;
  if not m_boDealing and (btWhere in [0..MAX_ENTOPTICPLACE - 1]) then begin
    if m_boPneuma and (m_PneumaObject <> nil) and (m_EntopticItems[btWhere].Item.wIndex > 0) then begin
      StdItem := UserEngine.GetStdItem(m_EntopticItems[btWhere].Item.wIndex);
      if (StdItem <> nil) and (StdItem.StdMode = 91) then begin
        if GetFetchBoneLevel(StdItem.Shape) >= GetPlaceLevel() then begin
          w := UserEngine.GetStdItemIdx(sItemName);
          if w > 0 then begin
            for i := m_ItemList.Count - 1 downto 0 do begin
              UserItem := pTUserItem(m_ItemList[i]);
              if UserItem^.wIndex = w then begin
                btKismet := GetRandomKismet();
                if btKismet > 0 then begin
                  AddGameDataLog('10' + #9 +
                    m_sMapName + #9 +
                    IntToStr(m_nCurrX) + #9 +
                    IntToStr(m_nCurrY) + #9 +
                    m_sCharName + #9 +
                    sItemName + #9 +
                    IntToStr(UserItem.MakeIndex) + #9 +
                    '1' + #9 +
                    sGameLogMsg);

                  SendDelItems(UserItem);
                  Dispose(pTUserItem(m_ItemList[i]));
                  m_ItemList.Delete(i);

                  m_EntopticItems[btWhere].Kismet[btPlace] := btKismet;
                  SendHeartFatePoint();

                  RecalcAbilitys();
                  SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

                  Result := True;
                end else
                  btError := 2;
                Break;
              end;
            end;
          end;
        end else
          btError := 1;
        if not Result then begin
          if btError = 2 then
            TPlayObject(m_PneumaObject).SendDefMessage(38288, 1, 255, 0, 0,
              sExceptionMsg3)
          else if btError = 1 then
            TPlayObject(m_PneumaObject).SendDefMessage(38288, 1, 255, 0, 0,
              sExceptionMsg2)
          else
            TPlayObject(m_PneumaObject).SendDefMessage(38288, 1, 255, 0, 0,
              sExceptionMsg1)
        end;
      end;
    end;
  end;
end;

procedure TPlayObject.SendHeartFatePoint();
var
  i                                     : Integer;
  Kismets                               : array[0..MAX_ENTOPTICPLACE - 1] of TKismet;
begin
  if m_boPneuma then begin
    for i := 0 to MAX_ENTOPTICPLACE - 1 do
      Kismets[i] := m_EntopticItems[i].GetKismet()^;
    SendMsg(Self, RM_HEARTFATEPOINT, 0, 0, 0, 0, EnCodeBuffer(@Kismets, SizeOf(Kismets)));
  end;
end;

//天元心法控制元神

procedure TPlayObject.ClientCtrlMental(wOpCode: word);
var
  nDW                                   : DWORD;
  PneumaObj                             : TPlayObject;
  StdItem                               : pTStdItem;
resourcestring
  sErrorMsg1                            = '你的内敛元神还未凝入头部魂骨或是还未点亮相应的心命点,无法进行切换。';
  sErrorMsg2                            = '你的外现元神还未凝入头部魂骨或是还未点亮相应的心命点,无法进行切换。';
  sErrorMsg3                            = '你的内敛元神还未凝入脊椎魂骨或是还未点亮相应的心命点,你的神智无法附身到你的外现元神上。';
  sErrorMsg4                            = '你的内敛元神还未凝入躯干魂骨或是还未点亮相应的心命点,你的神智无法附身到你的外现元神上。';
begin
  if m_boGhost or m_boDeath then Exit;
  if (m_PneumaObject = nil) or not (m_PneumaObject is TPlayObject) or
    (m_PneumaObject.m_boGhost) or (m_PneumaObject.m_boDeath) then Exit;
  PneumaObj := TPlayObject(m_PneumaObject);
  case wOpCode of
    1: begin
        if m_boCtrlMental then Exit;
        if PneumaObj.m_boInosculatePneuma then begin
          SysMsg('元神融合时不可进行此操作。', c_Red, t_Hint);
          Exit;
        end;
        if (GetTickCount - PneumaObj.m_dwLogonTick) >= 59000 then begin
          if (PneumaObj.m_EntopticItems[0].Item.wIndex > 0) then begin
            StdItem := UserEngine.GetStdItem(PneumaObj.m_EntopticItems[0].Item.wIndex);
            if (StdItem <> nil) and (StdItem.StdMode = 91) and
              (PneumaObj.m_EntopticItems[0].IsPlaceIllume(StdItem.Shape)) then begin
              if ((PneumaObj.m_btPneumaSex and $07) shr 2) <> 1 then begin
                SysMsg(sErrorMsg1, c_Red, t_Hint);
                Exit;
              end;
              PneumaObj.ClientSwitchPneuma();
            end else
              SysMsg(sErrorMsg2, c_Red, t_Hint);
          end else
            SysMsg(sErrorMsg2, c_Red, t_Hint);
        end;
      end;
    2: begin
        //检查是否装备了脊椎骨
        if m_boCtrlMental then begin
          //元神  =》 主体
          nDW := DWORD(Self);
          PneumaObj.SendRefMsg(RM_510, LoWord(nDW), HiWord(nDW), 127, 0, '');
          PneumaObj.SendDelayMsg(Self, RM_CTRLMENTAL, 0, Integer(PneumaObj), 258, 0, '', 1500);
          m_boCtrlMental := not m_boCtrlMental;
          ExecuteScript(g_FunctionNPC, '@元主切换触发');
        end else begin
          //主体 =》元神
          if ((PneumaObj.m_btPneumaSex and $0F) shr 3) <> 1 then begin
            SysMsg(sErrorMsg3, c_Red, t_Hint);
            Exit;
          end;

          if (PneumaObj.m_EntopticItems[1].Item.wIndex > 0) then begin
            StdItem := UserEngine.GetStdItem(PneumaObj.m_EntopticItems[1].Item.wIndex);
            if (StdItem <> nil) and (StdItem.StdMode = 91) and
              (PneumaObj.m_EntopticItems[1].IsPlaceIllume(StdItem.Shape)) then begin
              nDW := DWORD(PneumaObj);
              SendRefMsg(RM_510, LoWord(nDW), HiWord(nDW), 127, 0, '');
              SendDelayMsg(Self, RM_CTRLMENTAL, 0, Integer(Self), 258, 1, '', 1500);
              m_boCtrlMental := not m_boCtrlMental;
              ExecuteScript(g_FunctionNPC, '@主元切换触发');
            end;
          end;
        end;
      end;
    3: begin
        if ((PneumaObj.m_btPneumaSex and $1F) shr 4) <> 1 then begin
          SysMsg(sErrorMsg4, c_Red, t_Hint);
          Exit;
        end;
        PneumaObj.ClientInosculatePneuma();
        ExecuteScript(g_FunctionNPC, '@融合元神触发');
      end;

  end;
end;

//取人物外观扩展属性(翅膀、马等)

function TPlayObject.GetFeatureEx(): byte;
var
  Hum                                   : TPlayObject;
  btType, btReLive                      : byte;
  boRideDragon, boRideOrthrus           : Boolean;
begin
  if m_boFlyer then begin
    Result := $70 + 15;
    Exit;
  end;

{$IF USESDK = DEBUG}
  if m_nTestNumber <> 0 then begin
    Result := m_nTestNumber;
    Exit;
  end;
{$IFEND}

  Result := 0;
  btType := 0;
  btReLive := 0;
  if m_boRideOn then begin
    if m_boPneuma and (m_PneumaObject <> nil) then begin
      Hum := TPlayObject(m_PneumaObject);
      btType := Hum.m_PetInfo[3].btType;
      btReLive := Hum.m_PetInfo[3].btReLive;
    end else begin
      Hum := TPlayObject(Self);
      btType := Hum.m_PetInfo[2].btType;
      btReLive := Hum.m_PetInfo[2].btReLive;
    end;
    boRideDragon := Hum.m_boRideDragonMode;
    boRideOrthrus := Hum.m_boRideOrthrusMode;
    if btType < 11 then begin
      case m_btHorseType of
        1..5: Result := $E0 + m_btHorseType;                                                        //马
        6..10: Result := $A2 + m_btHorseType;                                                       //幽影铁骑、赤炎追风、踏雪银驹
      end;
    end else begin
      case btType of
        11..13: begin                                                                               //豹子
            case btReLive of
              1: Result := $DB + btType;                                                            //225- 227
              2: Result := $DE + btType;                                                            //228 -230
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $9C
                  else
                    Result := $81 + btType;                                                         //A4 5E 21 D7
                end;
            end;
          end;
        14..16: begin
            case btReLive of                                                                        //狮子
              1: Result := $EB + btType;
              2: begin
                  if btType = 11 then
                    Result := $F8
                  else
                    Result := $EE + btType;                                                         //$F8 红狮
                end;                                                                                //$D3 红狮
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $9D
                  else
                    Result := $81 + btType;
                end;
            end;
          end;
        17..19: begin
            case btReLive of                                                                        //麒麟
              1: Result := $DD + btType;
              2: Result := $E0 + btType;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $9F
                  else
                    Result := $81 + btType;
                end;
            end;
          end;
        20..22: begin
            case btReLive of                                                                        //凤凰
              1: Result := $68 + btType;
              2: Result := $6B + btType;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $A0
                  else
                    Result := $81 + btType;
                end;
            end;
          end;
        23..25: begin
            case btReLive of                                                                        //老虎
              1: ;
              2: Result := $82;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $A3
                  else
                    Result := $81 + btType;
                end;
            end;
          end;
        26..27: begin
            case btReLive of                                                                        //鲨鱼
              1: ;
              2: Result := $75 + btType;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $A1
                  else
                    Result := $7D + btType;
                end;
            end;
          end;
        28: ;
        29..31: begin
            case btReLive of                                                                        //帝王裂天犀
              1: ;
              2: Result := $85;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $A2
                  else
                    Result := $A2;
                end;
            end;
          end;
        32..34: begin                                                                               //独角兽
            case btReLive of
              1: ;
              2: ;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $AC + btType
                  else
                    Result := $A9 + btType;
                end;
            end;
          end;
        35..37: begin                                                                               //战马
            case btReLive of
              1: ;
              2: ;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $A2 + btType
                  else
                    Result := $9F + btType;
                end;
            end;
          end;
        38: begin                                                                                   //狼
            case btReLive of
              1: ;
              2: ;
              3: ;
              4: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $8A + btType
                  else
                    Result := $87 + btType;
                end;
            end;
          end;
        39: begin
            case btReLive of
              2: Result := $AD;                                                                     //二转邪影银月狼
            end;
          end;
        40: ;
        41..43: begin
            case btReLive of                                                                        //$B4 霜血战熊 $B3 双头兽 $B0 蓝色狼闪电 $AF 金色 独角 $AE 独角红色  $AD 独角蓝色 $AA 黑色战马  霜雪战熊
              1: ;
              2: ;
              3: begin
                  if m_boPneuma and m_boInosculatePneuma then
                    Result := $B4
                  else
                    Result := $B4;
                end;
              4: Result := $B4;
            end;
          end;
        44: begin                                                                                   //蓝焰战马
            case btReLive of
              2: Result := $C3;
            end;
          end;
        45: begin                                                                                   //绿焰战马
            case btReLive of
              2: Result := $C4;
            end;
          end;
        46: begin
            case btReLive of                                                                        //赤焰战马
              2: Result := $C2;
            end;
          end;
        47: begin                                                                                   //狂怒战熊
            case btReLive of
              4: Result := $B8;
            end;
          end;
      end;
      //沙城金龙
      if boRideDragon then begin
        if m_boPneuma and m_boInosculatePneuma then
          Result := $A6
        else
          Result := $A5;
      end;
      if boRideOrthrus then begin
        if m_boPneuma and m_boInNonSuchPavilion then
          Result := $B4
        else
          Result := $B3
      end;
    end;
  end;
end;

function TPlayObject.GetFeature(BaseObject: TBaseObject): Integer;
var
  StdItem                               : pTStdItem;
  btWeapon                              : byte;
  btRace, btHair, btDress, btDressShape : byte;
begin
  if m_boPneuma and m_boInosculatePneuma then begin
    btDress := 0;
    btDressShape := m_nDressShape;

    if m_TorDDM.Tiger.Items[U_DRESS].wIndex > 0 then begin                                          //衣服
      StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[U_DRESS].wIndex);
      if StdItem <> nil then begin
        //衣服有16种颜色,所以序号*16,再加上颜色
        btDress := (StdItem.Shape shl 4) + (m_TorDDM.Tiger.Items[U_DRESS].btValue[14] and $0F);

        if ((btDressShape and $000000C8) <> $000000C8) then btDressShape := StdItem.Shape;
      end;
    end else if ((btDressShape and $000000C8) <> $000000C8) then btDressShape := 28 + m_btJob;

    btWeapon := 0;                                                                                  //武器
    if m_TorDDM.Tiger.Items[U_WEAPON].wIndex > 0 then begin
      StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[U_WEAPON].wIndex);
      if StdItem <> nil then begin
        btWeapon := StdItem.Shape;
      end;
    end;

    m_nDressShape := MakeLong(MakeWord(btDressShape, 0), HiWord(m_nDressShape));
    btHair := m_btHair;                                                                             //头发
    btRace := GetFeatureEx;                                                                         //种族
    Result := MakeHumanFeature(btRace, btDress, btWeapon, btHair);
  end else
    Result := inherited GetFeature(BaseObject);
end;

function TPlayObject.GetAmbitStatus(): Integer;
var
  nNum                                  : Integer;
begin
  Result := inherited GetAmbitStatus();
  //传世主宰者 星星数量
  if (m_btRulerLevel > 0) then begin
    nNum := m_btRulerLevel * 8;
    Result := Result or nNum;
  end;
end;

function TPlayObject.GetMagicExStatus(): byte;
begin
  Result := inherited GetMagicExStatus();
  //传世主宰者
  if (m_btRulerLevel > 0) then Result := $80 or Result;
  if m_boPneuma then begin
    if m_boInosculatePneuma then begin
      Result := ($80 shr 4) or Result;                                                              //是融合元神
      Result := Result + (m_btPneumaSex and $03);                                                   //内敛元神职业  //元神里是用来保存内敛元神职业的
    end;
  end;
end;

procedure TPlayObject.ClientInosculatePneuma();
var
  MainPlayObj                           : TPlayObject;
  StdItem                               : pTStdItem;
  i, ii, n                              : Integer;
  Slave                                 : TBaseObject;
  RidePet                               : TRidePet;
resourcestring
  sErrorMsg                             = '你的外现元神还未凝入躯干魂骨或是还未点亮相应的心命点,你的神智无法附身到你的外现元神上。';
begin
  if m_PneumaObject = nil then Exit;
  if m_pSwitchPneuma <> nil then Exit;
  if (not m_boPneuma) or m_boCtrlMental then Exit;
  MainPlayObj := TPlayObject(m_PneumaObject);

  //  if m_boRideOn then begin
  //    MainPlayObj.SysMsg('元神骑乘模式下,不可进行此操作。', c_Red, t_Hint);
  //    Exit;
  //  end;

  if MainPlayObj.m_btCurPneumaCount < 2 then Exit;

  if MainPlayObj.m_boGhost or
    MainPlayObj.m_boDeath or
    MainPlayObj.m_boSoftClose or
    MainPlayObj.m_boReconnection then Exit;

  if m_boGhost or m_boDeath then Exit;

  if not m_boInosculatePneuma then begin
    if (GetTickCount - m_dwInosculateTick) >= 60000 then begin
      if (m_EntopticItems[2].Item.wIndex > 0) then begin
        StdItem := UserEngine.GetStdItem(m_EntopticItems[2].Item.wIndex);
        if (StdItem <> nil) and (StdItem.StdMode = 91) and
          (m_EntopticItems[2].IsPlaceIllume(StdItem.Shape)) then begin
          m_dwInosculateTick := GetTickCount;
          m_boInosculatePneuma := True;
          MainPlayObj.SendMsg(MainPlayObj, RM_CTRLMENTAL, 0, 0, 3, 0, '');
          //计算战斗值
          i := -1;
          if (m_btAmbitKind > 2) then Inc(i);
          if (m_btAmbitKind > 4) then Inc(i);
          if (m_btAmbitKind > 6) then Inc(i);
          if (m_btAmbitKind > 8) then Inc(i);
          if (m_btAmbitKind < 3) then i := 0;
          i := i * 99;
          //m_wInnerPneumaLevel  为内敛元神综合等级
          m_wCurFightValue := Round(((m_wInnerPneumaLevel + m_Abil.level + m_btAmbitLevel + i) / 5) + (MainPlayObj.m_btMentalLevel / 2));

          m_InosculatePneumaHP := m_WAbil.dwHP;                                                     //备份元神当前血
          m_InosculatePneumaMP := m_WAbil.dwMP;                                                     //备份融合元神当前蓝
          m_WAbil.dwHP := MainPlayObj.m_InosculatePneumaHP;                                         //当前融合的血值是保存主体身上的
          m_WAbil.dwMP := MainPlayObj.m_InosculatePneumaMP;                                         //当前融合的魔法值是保存主体身上的
          if m_WAbil.dwHP <= Round(m_WAbil.dwMaxHP * 10 / 100) then
            m_WAbil.dwHP := m_WAbil.dwMaxHP;

          FillChar(m_InosculatePneumaAddAbil, SizeOf(TAddAbility), #0);
          //
          //计算属性                                                                                // 14 + 85 +20 42 * 338
          if (m_btJob = 0) and ((m_btPneumaSex and $03) = 1) then begin                             //战战 14 + (122 / 2 + 20 + 122 / 4) * (122 * 2)
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 2 + 20 + m_wCurFightValue / 4) * (m_wCurFightValue * 2))));
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round(m_wCurFightValue * 12));
            n := _Max((m_wCurFightValue * 6 div 8) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wSC := 0;
            m_InosculatePneumaAddAbil.wMC := 0;
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue * 6 div 12));
            m_InosculatePneumaAddAbil.wMAC := MakeLong(0, (m_wCurFightValue div 20));
          end else if (m_btJob = 1) and ((m_btPneumaSex and $03) = 2) then begin                    //法法  14 + (122 / 3 + 20) * 122
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 3 + 10) * m_wCurFightValue))); //14 + (122 / 2 + 20) * 4.4 * 122
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round((m_wCurFightValue / 2 + 20) * 4.4 * m_wCurFightValue));

            n := _Max((m_wCurFightValue * 6 div 9) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wMC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wSC := 0;
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue div 22));
            m_InosculatePneumaAddAbil.wMAC := MakeLong(0, (m_wCurFightValue div 18));
          end else if (m_btJob = 2) and ((m_btPneumaSex and $03) = 3) then begin                    //道道
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 2 + 30) * m_wCurFightValue)));
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round(((m_wCurFightValue / 3) * 3.3 * m_wCurFightValue)));
            n := _Max((m_wCurFightValue * 6 div 9) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wMC := 0;
            m_InosculatePneumaAddAbil.wSC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue div 18));
            n := _Max((m_wCurFightValue * 6 div 12), 1);
            m_InosculatePneumaAddAbil.wMAC := MakeLong(n div 2, n + 1);
          end else if (m_btJob in [0, 1]) and ((m_btPneumaSex and $03) in [1, 2]) then begin        //战法
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 2 + 10 + m_wCurFightValue / 4) * (m_wCurFightValue * 1.5))));
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round((m_wCurFightValue / 2 + 10) * 2.2 * m_wCurFightValue));
            n := _Max((m_wCurFightValue * 6 div 10) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wSC := 0;
            m_InosculatePneumaAddAbil.wMC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue * 6 div 14));
            m_InosculatePneumaAddAbil.wMAC := MakeLong(0, (m_wCurFightValue div 18));
          end else if (m_btJob in [0, 2]) and ((m_btPneumaSex and $03) in [1, 3]) then begin        //战道
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 3 + 15 + m_wCurFightValue / 4) * (m_wCurFightValue * 1.5))));
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round(((m_wCurFightValue / 4) * 2.2 * m_wCurFightValue)));
            n := _Max((m_wCurFightValue * 6 div 10) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wMC := 0;
            m_InosculatePneumaAddAbil.wSC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue div 22));
            n := _Max((m_wCurFightValue * 6 div 18), 1);
            m_InosculatePneumaAddAbil.wMAC := MakeLong(n div 2, n + 1);
          end else if (m_btJob in [1, 2]) and ((m_btPneumaSex and $03) in [2, 3]) then begin        //法道
            m_InosculatePneumaMaxHP := _MIN(MAXHUMHP, 14 + Round(((m_wCurFightValue / 3 + 15) * m_wCurFightValue)));
            m_InosculatePneumaMaxMP := _MIN(MAXHUMMP, 13 + Round(((m_wCurFightValue / 3) * 2.2 * m_wCurFightValue)));
            n := _Max((m_wCurFightValue * 6 div 10) - 1, 1);
            m_InosculatePneumaAddAbil.wDC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wMC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wSC := MakeLong(n - 1, n);
            m_InosculatePneumaAddAbil.wAC := MakeLong(0, (m_wCurFightValue div 22));
            n := _Max((m_wCurFightValue * 6 div 14), 1);
            m_InosculatePneumaAddAbil.wMAC := MakeLong(n div 2, n + 1);
          end;

          //如果是0血,则加满血
          if m_WAbil.dwHP = 0 then
            m_WAbil.dwHP := m_InosculatePneumaMaxHP;

          //Min(m_InosculatePneumaMaxHP, m_WAbil.dwHP);
          //Min(m_InosculatePneumaMaxMP, m_WAbil.dwMP);

          //发送本人物所学习了的技能列表
          SendUseMagic();
          //发送融合元神身上物品
          SendTigerItem();

          FeatureChanged();
          MainPlayObj.SendMsg(MainPlayObj, RM_CTRLMENTAL, 0, Integer(MainPlayObj), 259, 1, '');
        end;
      end;

      if not m_boInosculatePneuma then begin
        MainPlayObj.SysMsg(sErrorMsg, c_Red, t_Hint);
        Exit;
      end;
    end;
  end else begin
    m_boInosculatePneuma := False;

    if m_SpiritInfo.boMag then begin
      SendRefMsg(RM_SPIRITHP, 0, 0, 0, 0, '');
      m_SpiritInfo.boMag := False;                                                                  //取消技能的使用
    end;

    MainPlayObj.SendMsg(MainPlayObj, RM_CTRLMENTAL, 0, Integer(MainPlayObj), 259, 0, '');
    //装备更换

    MainPlayObj.m_InosculatePneumaHP := m_WAbil.dwHP;                                               //把当前融合的血值保存主体身上
    MainPlayObj.m_InosculatePneumaMP := m_WAbil.dwMP;                                               //把当前融合的魔法值保存主体身上

    m_WAbil.dwHP := m_InosculatePneumaHP;                                                           //还原元神当前血
    m_WAbil.dwMP := m_InosculatePneumaMP;                                                           //还原元神当前魔法值

    //发送本人物所学习了的技能列表
    SendUseMagic();
    //发送身上物品
    //SendUseitems();
    FeatureChanged();
  end;

  //{取消魔法盾,护身真气,金刚护体等下线保存}
  m_wStatusTimeArr[STATE_BUBBLEDEFENCEUP] := 1;
  m_wStatusTimeArr[STATE_JINGANGHUTI] := 1;
  m_wStatusTimeArr[STATE_HUSHENZHENQI] := 1;
  m_wStatusTimeArr[STATE_FENGYINGDUN] := 1;
  m_wStatusTimeArr[STATE_FIERYDRAGON] := 1;
  m_wStatusTimeArr[STATE_HELLINTENSEFLAME] := 1;
  m_boAbilMag70Defence := False;
  m_boAbilMagHuShenDefence := False;
  m_boAbilMagJingangDefence := False;
  m_boAbilMagBubbleDefence := False;
  //清除宝宝
  for i := 0 to m_SlaveList.Count - 1 do begin
    Slave := TBaseObject(m_SlaveList.Items[i]);
    //通知元神宝宝ID
    ii := Integer(Slave);
    SendDefMessage(SM_SLAVEINFO, Integer(Self), 0, 0, 1, EnCodeBuffer(@ii, SizeOf(Integer)));
    //m_defMsg := MakeDefaultMsg(SM_SLAVEINFO, Integer(Self), 0, 0, 1);
    //SendSocket(@m_defMsg, EnCodeBuffer(@ii, SizeOf(Integer)));
    Slave.MakeGhost();
  end;
  m_SlaveList.Clear;



  //刷新自身信息 到客户端
  RecalcHitSpeed;
  RecalcAbilitys();
  SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
  SendUpdateMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');


    SendRefMsg(RM_TURN, m_btDirection, m_nCurrX, m_nCurrY, CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), GetShowName);

end;

procedure TPlayObject.ClientSwitchPneuma();
var
  MainPlayObj                           : TPlayObject;
begin
  if m_PneumaObject = nil then Exit;
  if m_pSwitchPneuma <> nil then Exit;
  if not m_boPneuma then Exit;
  MainPlayObj := TPlayObject(m_PneumaObject);

  if MainPlayObj.m_btCurPneumaCount < 2 then Exit;

  if MainPlayObj.m_boGhost or
    MainPlayObj.m_boDeath or
    MainPlayObj.m_boSoftClose or
    MainPlayObj.m_boReconnection then Exit;

  if m_boGhost or m_boDeath then Exit;

  New(m_pSwitchPneuma);
  try
    MainPlayObj.m_PneumaObject := nil;
    MainPlayObj.m_nPneumaLastX := m_nCurrX;
    MainPlayObj.m_nPneumaLastY := m_nCurrY;
    TPlayObject(m_PneumaObject).m_PetInfo[3].nMakeIndex := 0;
    TPlayObject(m_PneumaObject).m_PetInfo[3].wLevel := 0;
    TPlayObject(m_PneumaObject).m_PetInfo[3].btType := 0;
    TPlayObject(m_PneumaObject).m_PetInfo[3].btReLive := 0;
    TPlayObject(m_PneumaObject).m_PetInfo[3].btRideFightSpeed := 0;
    m_PneumaObject := nil;
    m_boSoftClose := True;
    m_boReconnection := True;
    SendRefMsg(RM_510, 1, 0, 42, 0, '');
    SendDefMessage(SM_OUTOFCONNECTION, 0, 0, 0, 0, '');
    MainPlayObj.m_dwCallPneumaTick := GetTickCount;

    m_pSwitchPneuma^.dwPlayObject := Integer(MainPlayObj);
    m_pSwitchPneuma^.sChrName := m_sCharName;
    m_pSwitchPneuma^.dwDBIndex := m_dwDBIndex;

    //在主体上保存一下当前的最大攻击吧
    case m_btJob of
      0: MainPlayObj.m_SpiritInfo.wWithinTotalDC := hiword(m_WAbil.DC);
      1: MainPlayObj.m_SpiritInfo.wWithinTotalDC := hiword(m_WAbil.MC);
      2: MainPlayObj.m_SpiritInfo.wWithinTotalDC := hiword(m_WAbil.SC);
    end;

  except
    Dispose(m_pSwitchPneuma);
    m_pSwitchPneuma := nil;
  end;
end;

procedure TPlayObject.ClientTakeOnInosculatePneumaItem(nWhere, nMakeIndex: Integer);
var
  i, n14, n18                           : Integer;
  UserItem, TakeoffItem                 : pTUserItem;
  StdItem, StdItem20                    : pTStdItem;
  StdItem58                             : TStdItem;
  boCanTakeOn                           : Boolean;
label
  FailExit;
begin
  StdItem := nil;
  UserItem := nil;
  n14 := -1;

  if m_boPneuma and m_boInosculatePneuma then begin
    //灵珠状态下不能使用武器
    if (nWhere = U_WEAPON) and m_boPneumaEffMode then Exit;

    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];                                                              //包裹里的物品
      if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        n14 := i;
        Break;
      end;
      StdItem := nil;
      UserItem := nil;
    end;
  end;

  n18 := 0;
  if (StdItem <> nil) and (UserItem <> nil) then begin
    if CheckIPUserItems(nWhere, StdItem) and (StdItem.Need = 09) then begin
      //物品控制-禁止元神、红名、本体穿戴
      if m_boPneuma then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEPNEUMATAKEON))
      else if (PKLevel > 2) then
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEREDTAKEON))
      else
        boCanTakeOn := not (CheckSPCode(StdItem.SPCode, SP_DISABLEHUMANTAKEON));

      if not boCanTakeOn then begin
        SysMsg('你不能佩戴此物品。', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;

      StdItem58 := StdItem^;
      ItemUnit.GetItemAddValue(UserItem, StdItem58);
      if (n18 = 0) and CheckTakeOnItems(U_ENTOPTIC, StdItem58) and CheckItemBindUse(UserItem) then begin
        TakeoffItem := nil;
        if nWhere in [Low(m_TorDDM.Tiger.Items)..High(m_TorDDM.Tiger.Items)] then begin
          //取下物品
          if m_TorDDM.Tiger.Items[nWhere].wIndex > 0 then begin                                     //当前位置已装备了物品,则取下
            StdItem20 := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[nWhere].wIndex);
            if (StdItem20 <> nil) then begin
              if not m_boUserUnLockDurg and ((StdItem20.Reserved and 2) <> 0) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;                                                                                  //004DAE78
              if (StdItem20.Reserved and 4) <> 0 then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
              //物品控制-禁止取下物品
              if CheckSPCode(StdItem20.SPCode, SP_DISABLETAKEOFF) then begin
                SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
                n18 := -4;
                goto FailExit;
              end;
            end;

            New(TakeoffItem);
            TakeoffItem^ := m_TorDDM.Tiger.Items[nWhere];
          end;

          m_TorDDM.Tiger.Items[nWhere] := UserItem^;

          DelBagItem(n14);
          if TakeoffItem <> nil then begin
            AddItemToBag(TakeoffItem);
            SendAddItem(TakeoffItem);
          end;

          n18 := 1;
          SendDefMessage(SM_TAKEON_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');

          RecalcAbilitys();
          SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
          SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

          FeatureChanged();

          if (m_btJob = 0) and (nWhere in [0..1]) then
            SendRefMsg(RM_TURN, m_btDirection, m_nCurrX, m_nCurrY,
              CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), '');
        end;
      end else n18 := -1;
    end else n18 := -1;
  end;
  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEON_FAIL, n18, 0, 0, 0, '');
end;

procedure TPlayObject.ClientTakeOffInosculatePneumaItem(nWhere, nMakeIndex: Integer);
var
  N10, i                                : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  sName                                 : string;
  nCheckCode                            : Integer;
label
  FailExit;
begin
  N10 := 0;
  nCheckCode := 0;
  if m_boPneuma and m_boInosculatePneuma then begin
    if not m_boDealing and (nWhere in [Low(m_TorDDM.Tiger.Items)..High(m_TorDDM.Tiger.Items)]) then begin
      if m_TorDDM.Tiger.Items[nWhere].wIndex > 0 then begin
        if m_TorDDM.Tiger.Items[nWhere].MakeIndex = nMakeIndex then begin
          StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[nWhere].wIndex);
          if (StdItem <> nil) then begin
            //物品控制-禁止取下物品
            if CheckSPCode(StdItem.SPCode, SP_DISABLETAKEOFF) then begin
              SysMsg(g_sCanotTakeOffItem {'无法取下物品!!!'}, c_Red, t_Hint);
              N10 := -4;
              goto FailExit;
            end;

            New(UserItem);
            UserItem^ := m_TorDDM.Tiger.Items[nWhere];
            if AddItemToBag(UserItem) then begin
              m_TorDDM.Tiger.Items[nWhere].wIndex := 0;

              SendAddItem(UserItem);
              SendDefMessage(SM_TAKEOFF_OK, GetFeatureToLong(Self), GetGender, 0, 0, '');

              RecalcAbilitys();
              SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
              SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');

              FeatureChanged();
              if (m_btJob = 0) and (nWhere = 0) then
                SendRefMsg(RM_TURN, m_btDirection, m_nCurrX, m_nCurrY,
                  CalcCent(m_WAbil.dwHP, m_WAbil.dwMaxHP), '');
            end else begin
              Dispose(UserItem);
              N10 := -3;
            end;
          end;
        end;
      end else N10 := -2;
    end else N10 := -1;
  end else N10 := -4;

  FailExit:
  if N10 <= 0 then
    SendDefMessage(SM_TAKEOFF_FAIL, N10, 0, 0, 0, '');
end;

procedure TPlayObject.RecalcAddInosculatePneumaAbil();
var
  i                                     : Integer;
  StdItem                               : pTStdItem;
begin
  if not m_boPneuma or not m_boInosculatePneuma then Exit;

  for i := Low(TTigerItems) to High(TTigerItems) do begin
    if (m_TorDDM.Tiger.Items[i].wIndex <= 0) or (m_TorDDM.Tiger.Items[i].Dura <= 0) then
      Continue;                                                                                     //物品不存在或物品已损坏
    StdItem := UserEngine.GetStdItem(m_TorDDM.Tiger.Items[i].wIndex);
    if StdItem = nil then Continue;

    //获得物品的附加属性
    GetAccessory(m_TorDDM.Tiger.Items[i], m_AddAbil);

    //武器
    if (i = U_WEAPON) then begin
      if (StdItem.Source - 1 - 10) < 0 then
        m_AddAbil.btWeaponStrong := StdItem.Source;                                                 //强度+
      if (StdItem.Source <= -1) and (StdItem.Source >= -50) then                                    // -1 至 -50
        m_AddAbil.btSacred := m_AddAbil.btSacred + -StdItem.Source;                                 //神圣+
      if (StdItem.Source <= -51) and (StdItem.Source >= -100) then                                  // -51 至 - 100
        m_AddAbil.btSacred := m_AddAbil.btSacred + (StdItem.Source + 50);                           //神圣-
    end;
  end;

  //神魂融合增加血上线与攻击
  if m_SpiritInfo.boMag then begin
    Inc(m_AddAbil.dwHP, m_SpiritInfo.wAddHP);
    case m_btJob of
      0: m_AddAbil.wDC := MakeLong(LoWord(m_AddAbil.wDC), HiWord(m_AddAbil.wDC) + m_SpiritInfo.wAddDC);
      1: m_AddAbil.wMC := MakeLong(LoWord(m_AddAbil.wMC), HiWord(m_AddAbil.wMC) + m_SpiritInfo.wAddDC);
      2: m_AddAbil.wSC := MakeLong(LoWord(m_AddAbil.wSC), HiWord(m_AddAbil.wSC) + m_SpiritInfo.wAddDC);
      3: m_AddAbil.dwGC := MakeLong(LoWord(m_AddAbil.dwGC), HiWord(m_AddAbil.dwGC) + m_SpiritInfo.wAddDC);
    end;
  end;

  Inc(m_AddAbil.wSpeedPoint, m_InosculatePneumaAddAbil.wSpeedPoint);                                //躲避
  Inc(m_AddAbil.wHitPoint, m_InosculatePneumaAddAbil.wHitPoint);                                    //人物攻击命中(Byte)
  Inc(m_AddAbil.wAntiPoison, m_InosculatePneumaAddAbil.wAntiPoison);                                //中毒躲避
  Inc(m_AddAbil.wPoisonRecover, m_InosculatePneumaAddAbil.wPoisonRecover);                          //中毒恢复
  Inc(m_AddAbil.wHealthRecover, m_InosculatePneumaAddAbil.wHealthRecover);                          //生命恢复
  Inc(m_AddAbil.wSpellRecover, m_InosculatePneumaAddAbil.wSpellRecover);                            //魔法恢复
  Inc(m_AddAbil.wAntiMagic, m_InosculatePneumaAddAbil.wAntiMagic);                                  //魔法躲避
  Inc(m_AddAbil.btMagicNicety, m_InosculatePneumaAddAbil.btMagicNicety);                            //魔法命中
  Inc(m_AddAbil.btPoisonNicety, m_InosculatePneumaAddAbil.btPoisonNicety);                          //中毒命中
  Inc(m_AddAbil.btLuck, m_InosculatePneumaAddAbil.btLuck);                                          //人物的幸运值
  Inc(m_AddAbil.btUnLuck, m_InosculatePneumaAddAbil.btUnLuck);                                      //人物的诅咒值
  Inc(m_AddAbil.nHitSpeed, m_InosculatePneumaAddAbil.nHitSpeed);                                    //攻击速度

  m_AddAbil.wAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wAC) + loword(m_InosculatePneumaAddAbil.wAC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.wAC) + hiword(m_InosculatePneumaAddAbil.wAC)));

  m_AddAbil.wMAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMAC) + loword(m_InosculatePneumaAddAbil.wMAC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.wMAC) + hiword(m_InosculatePneumaAddAbil.wMAC)));

  m_AddAbil.wDC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wDC) + loword(m_InosculatePneumaAddAbil.wDC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.wDC) + hiword(m_InosculatePneumaAddAbil.wDC)));

  m_AddAbil.wMC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMC) + loword(m_InosculatePneumaAddAbil.wMC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.wMC) + hiword(m_InosculatePneumaAddAbil.wMC)));

  m_AddAbil.wSC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wSC) + loword(m_InosculatePneumaAddAbil.wSC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.wSC) + hiword(m_InosculatePneumaAddAbil.wSC)));

  m_AddAbil.dwGC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.dwGC) + loword(m_InosculatePneumaAddAbil.dwGC)),
    _MIN(High(MaxInt), hiword(m_AddAbil.dwGC) + hiword(m_InosculatePneumaAddAbil.dwGC)));
end;

procedure TPlayObject.ClientQueryGuildClanList;
var
  sData, sClanName, sAmbit              : string;
  Clan                                  : TClan;
  i, ii                                 : Integer;
  ClanAmbit                             : pTClanAmbit;
begin
  if m_MyGuild = nil then Exit;
  sData := '';
  for i := 0 to TGuild(m_MyGuild).m_ClanList.Count - 1 do begin
    if i >= 50 then Break;
    sClanName := TGuild(m_MyGuild).m_ClanList.Strings[i];
    Clan := g_GuildManager.FindClan(sClanName);
    if Clan <> nil then begin
      sData := sData + '#' + Clan.m_sClanName + '/' + Clan.ChiefName + '/' + IntToStr(Clan.btClanKind) + '/';
      for ii := 0 to Clan.m_MemberList.Count - 1 do begin
        if ii >= 200 then Break;
        ClanAmbit := pTClanAmbit(Clan.m_MemberList.GetValues(Clan.m_MemberList.Keys[ii]));
        if (ClanAmbit.Ambit > 2) then begin
          if (ClanAmbit.Ambit mod 2) = 0 then
            sAmbit := '2'
          else
            sAmbit := '1';
        end else
          sAmbit := '0';
        sData := sData + Clan.m_MemberList.Keys[ii] + '/' + sAmbit + '/';
      end;
    end;
  end;
  SendDefMessage(CM_GUILDCLAN, 0, 0, 0, 0, sData);
end;

procedure TPlayObject.ClientClanOperate(nOpCode: Integer; sMsg: string);
var
  sName, ClanName                       : string;
  Hum                                   : TPlayObject;
  Clan                                  : TClan;
begin
  if (m_MyClan <> nil) then begin
    case nOpCode of
      0: begin                                                                                      //招收弟子
          sName := DeCodeString(sMsg);
          Hum := UserEngine.GetPlayObject(sName);
          if (Hum <> nil) then begin
            if CretInNear10XY(Hum, m_nCurrX, m_nCurrY) then begin
              if (Hum.m_MyGuild = m_MyGuild) then begin
                Clan := TClan(m_MyClan);
                if (Hum.m_MyClan = nil) and (Clan.ChiefName = m_sCharName) then begin
                  Hum.SendDefMessage(CM_CLANQUERY, 0, 1, 0, 0, m_sCharName);
                  Hum.m_sQueryName := m_sCharName;
                end else begin
                  SysMsg('对方已有宗族!', c_Red, t_Hint);
                end;
              end else
                SysMsg('对方和你不是同一行会,不能加入!', c_Red, t_Hint);
            end else
              SysMsg('想加入宗族的成员必须在族长附近。', c_Red, t_Hint);
          end;
        end;
      1: begin                                                                                      //开除弟子
          sName := DeCodeString(sMsg);
          if (sName <> m_sCharName) then begin
            Hum := UserEngine.GetPlayObject(sName);
            Clan := TClan(m_MyClan);
            if (Hum <> nil) and (Hum.m_MyClan <> nil) and (Clan.ChiefName = m_sCharName) then begin
              if (Hum.m_MyClan = m_MyClan) then begin
                Clan := TClan(Hum.m_MyClan);
                if Clan.DelMember(sName) then begin
                  Hum.m_MyClan := nil;
                  Hum.SendDefMessage(CM_CLANOPERATE, 0, 1, 0, 0, Clan.m_sClanName + '/' + sName);
                end;
              end else begin
                SysMsg('对方不是你的宗族弟子!', c_Red, t_Hint);
              end;
            end;
          end else
            SysMsg('不能删除自己', c_Red, t_Hint);
        end;
      2: begin                                                                                      //退出宗族
          Clan := TClan(m_MyClan);
          if (Clan <> nil) then begin
            if Clan.DelMember(m_sCharName) then begin
              m_MyClan := nil;
              SendDefMessage(CM_CLANOPERATE, 0, 1, 0, 0, Clan.m_sClanName + '/' + m_sCharName);
            end;
          end;
        end;
      3: begin                                                                                      //解散宗族
          Clan := TClan(m_MyClan);
          if (Clan.ChiefName = m_sCharName) then begin
            sName := Clan.m_sClanName;
            if Clan.CancelClan(m_sCharName) then begin
              g_GuildManager.DelClan(sName);
              SysMsg('成功解散宗族!', c_Red, t_Hint);
            end;
          end;
        end;
    end;
  end;
end;

procedure TPlayObject.ClientClanReQuery(nOpCode: Integer; sMsg: string);
var
  Hum                                   : TPlayObject;
  Clan                                  : TClan;
  Guild                                 : TGuild;
  sGuildName                            : string;
begin
  if (m_sQueryName <> '') then Hum := UserEngine.GetPlayObject(m_sQueryName);
  if (Hum <> nil) and (not m_boDeath) and (not m_boGhost) then begin
    Clan := TClan(Hum.m_MyClan);
    if (Clan <> nil) and (CompareStr(Clan.ChiefName, m_sQueryName) = 0) then begin
      case LoByte(nOpCode) of
        1: begin
            if (HiByte(nOpCode) = 1) then begin
              if (Clan <> nil) then begin
                if Clan.AddMember(Self) then begin
                  m_MyClan := Clan;
                  //如果宗族有行会,则需要加入该行会
                  if (Hum.m_MyGuild <> nil) and (m_MyGuild = nil) then begin
                    TGuild(Hum.m_MyGuild).AddMember(Self);
                    UserEngine.SendServerGroupMsg(SS_207, g_Config.nServerNumber, TGuild(Hum.m_MyGuild).sGuildName);
                    m_MyGuild := TGuild(Hum.m_MyGuild);
                    m_sGuildRankName := TGuild(Hum.m_MyGuild).GetRankName(Self, m_nGuildRankNo);
                    RefShowName();
                    SysMsg('你已加入行会: ' + TGuild(Hum.m_MyGuild).sGuildName + ' 当前封号为: ' + m_sGuildRankName, c_Green, t_Hint);
                  end;
                  SysMsg('成功加入宗族!', c_Red, t_Hint);
                  SendFiendList(4);
                  SendMeOnlineState(1, 4);
                end;
              end;
            end else begin
              Hum.SysMsg('对方不同意加入宗族!', c_Red, t_Hint);
            end;
          end;
      end;
    end;
  end;
end;

function TPlayObject.CheckMapRideOn(Envir: TEnvirnoment): Boolean;
var
  btType                                : byte;
begin
  Result := False;
  if Envir = nil then Exit;
  if (not m_PEnvir.m_MapFlag.boRideOn) and (m_btHorseType > 0) then Exit;

  if m_PEnvir.m_MapFlag.boNoRidePet or g_Config.boChMapRideOff then Exit;
  if m_boRideOn then begin
    if m_boPneuma and (m_PneumaObject <> nil) then
      btType := TPlayObject(m_PneumaObject).m_PetInfo[3].btType
    else
      btType := m_PetInfo[2].btType;
  end else
    btType := m_PetInfo[0].btType;

  if (btType in [26..28]) and (not m_PEnvir.m_MapFlag.boCanRideShark) then Exit;
  if not (btType in [26..28]) and (m_PEnvir.m_MapFlag.boWaterNeed) and (not m_boUnWater) then Exit;
  Result := True;
end;

//火龙附体

procedure TPlayObject.MagFieryDragonRun();
var
  i                                     : Integer;
  BaseObject                            : TBaseObject;
  nPower                                : Integer;
begin
  nPower := 0;
  if ((GetTickCount - m_dwFieryDragonRunTick) > 1000) then begin
    m_dwFieryDragonRunTick := GetTickCount();
    if (m_wStatusTimeArr[STATE_FIERYDRAGON] > 0) or (m_wStatusTimeArr[STATE_WARWHIRLWIND] > 0) or
      (m_wStatusTimeArr[STATE_FIREDRAGON] > 0) or (m_btRandomDanceTime > 0) then
    begin
      for i := 0 to m_VisibleActors.Count - 1 do begin
        BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors[i]).BaseObject);
        if (not BaseObject.m_boDeath) and (BaseObject <> Self) then begin
          if IsProperTarget(BaseObject) then begin
            if (abs(m_nCurrX - BaseObject.m_nCurrX) <= 3) and (abs(m_nCurrY - BaseObject.m_nCurrY) <= 3) then begin

            end;

            if (abs(m_nCurrX - BaseObject.m_nCurrX) <= 2) and (abs(m_nCurrY - BaseObject.m_nCurrY) <= 2) then begin
              //火龙附体
              if (m_wStatusTimeArr[STATE_FIERYDRAGON {火龙附体}] > 0) then begin
                nPower := m_wCurFightValue * 2;
                BaseObject.SendMsg(Self, RM_MAGSTRUCK, 0, nPower, SKILL_FIERYDRAGON, 0, '');
              end;

            end;
          end;
        end;
      end;
    end;
  end;
end;

//投石车攻击目标

procedure TPlayObject.ClientCatapultAttackTarget(nOpCode, nX, nY: Integer);
var
  MessageBody                           : TMessageBody3W;
begin
  if m_boDeath or m_boGhost then Exit;

  if (GetTickCount - m_dwCatapultAttackTick) < 3000 then Exit;

  if m_boCatapultMode and m_boCatapultAttackMode then begin
    if m_PEnvir.CanWalk(nX, nY, True) then begin
      //检测炮弹
      if nOpCode = 0 then begin
        MessageBody.wX := nX;
        MessageBody.wY := nY;
        MessageBody.wParam := 0;
        SendRefMsg(RM_LAPIDATION, 0, Integer(Self), nX, nY, EnCodeBuffer(@MessageBody, SizeOf(TMessageBody3W)));
      end else begin                                                                                //速射

      end;
      m_dwCatapultAttackTick := GetTickCount;
      //SendRefMsg(RM_CATAPULTATTACK, 0, Integer(Self), nX, nY, '');
      SendDefMessage(SM_CATAPULTATTACK, Integer(Self), nX, nY, 0, '');
    end else begin
      SysMsg('请向空地投弹', c_Red, t_Hint);
      SendDefMessage(SM_CATAPULTATTACK, Integer(Self), nX, nY, 1, '');
    end;
  end;
end;

//附加天元心法属性

procedure TPlayObject.RecalcMentalLevelAbilitys;
var
  MentalAbility                         : pTMentalAbility;
begin
  if m_boPneuma then Exit;

  MentalAbility := UserEngine.GetMentalAbil(m_btJob, m_btMentalLevel);
  if MentalAbility <> nil then begin
    m_nMentalPointMax := MentalAbility.MentalExp;
    m_AddAbil.dwHP := _MIN(MAXHUMHP, m_AddAbil.dwHP + MentalAbility.HP);
    case m_btJob of
      0: m_AddAbil.wDC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wDC) + MentalAbility.DC), _MIN(High(MaxInt), hiword(m_AddAbil.wDC) + MentalAbility.DC2));
      1: m_AddAbil.wMC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMC) + MentalAbility.DC), _MIN(High(MaxInt), hiword(m_AddAbil.wMC) + MentalAbility.DC2));
      2: m_AddAbil.wSC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wSC) + MentalAbility.DC), _MIN(High(MaxInt), hiword(m_AddAbil.wSC) + MentalAbility.DC2));
    end;
    m_AddAbil.wAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wAC) + MentalAbility.AC), _MIN(High(MaxInt), hiword(m_AddAbil.wAC) + MentalAbility.AC2));
    m_AddAbil.wMAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMAC) + MentalAbility.MAC), _MIN(High(MaxInt), hiword(m_AddAbil.wMAC) + MentalAbility.MAC2));
    m_AddAbil.wElementForceMax := _MIN(High(MaxInt), m_AddAbil.wElementForceMax + MentalAbility.ElementForce);
    m_AddAbil.btThump := _MIN(High(word), m_AddAbil.btThump + MentalAbility.Thump);
    m_AddAbil.wAgainst := _MIN(High(word), m_AddAbil.wAgainst + MentalAbility.Against);
    //MentalAbility.UnPalsy    抗麻痹
  end;
end;

procedure TPlayObject.ClientQueryMentalAbilitys(PlayObject: TPlayObject);
type
  TMentalPack = packed record
    btType: byte;
    wValue: word;
  end;
var
  MentalAbility                         : pTMentalAbility;
  NewMentalAbility                      : pTMentalAbility;
  MentalSet                             : array[0..7] of word;
  MentalPack                            : array[0..11] of TMentalPack;
  i, nCount                             : Integer;
  s, sName                              : string;
  Foresee                               : TStringList;
begin
  if PlayObject = nil then Exit;

  MentalSet[0] := MakeWord($01, $0B);
  MentalSet[1] := MakeWord($06, $01);
  MentalSet[2] := MakeWord($09, $01);
  MentalSet[3] := MakeWord($0A, $01);
  MentalSet[4] := MakeWord($0B, $11);
  MentalSet[5] := MakeWord($0C, $05);
  MentalSet[6] := MakeWord($0D, $14);
  MentalSet[7] := MakeWord($0E, $0B);
  m_defMsg := MakeDefaultMsg(CM_QUERYMENTAL, 0, 8, 0, 0);
  SendSocket(@m_defMsg, EnCodeBuffer(@MentalSet, 16));

  MentalAbility := UserEngine.GetMentalAbil(PlayObject.m_btJob, PlayObject.m_btMentalLevel);
  if MentalAbility <> nil then begin
    MentalPack[0].btType := $01;
    MentalPack[0].wValue := MakeWord(MentalAbility.DC, MentalAbility.DC2);
    MentalPack[1].btType := $06;
    MentalPack[1].wValue := MentalAbility.HP;
    MentalPack[2].btType := $09;
    MentalPack[2].wValue := MakeWord(MentalAbility.AC, MentalAbility.AC2);
    MentalPack[3].btType := $0A;
    MentalPack[3].wValue := MakeWord(MentalAbility.MAC, MentalAbility.MAC2);
    MentalPack[4].btType := $0B;
    MentalPack[4].wValue := MentalAbility.Thump;
    MentalPack[5].btType := $0C;
    MentalPack[5].wValue := MentalAbility.ElementForce;
    MentalPack[6].btType := $0D;
    MentalPack[6].wValue := MentalAbility.Against;
    MentalPack[7].btType := $0E;
    MentalPack[7].wValue := MentalAbility.UnPalsy;
    s := Trim(MentalAbility.Foresee);
    nCount := 0;
    if s <> '' then begin
      NewMentalAbility := UserEngine.GetMentalAbil(PlayObject.m_btJob, PlayObject.m_btMentalLevel + 1);
      if (MentalAbility <> nil) and (NewMentalAbility <> nil) then begin
        Foresee := TStringList.Create;
        try
          ExtractStrings([','], [], PChar(s), Foresee);
          for i := 0 to Foresee.Count - 1 do begin
            if nCount >= 6 then Break;
            sName := UpperCase(Foresee.Strings[i]);
            if (sName = 'DC') then begin
              MentalPack[8 + nCount].btType := $01;
              MentalPack[8 + nCount].wValue := MakeWord(NewMentalAbility.DC - MentalAbility.DC, NewMentalAbility.DC2 - MentalAbility.DC2);
              Inc(nCount);
              Continue;
            end;
            if (sName = 'HP') then begin
              MentalPack[8 + nCount].btType := $06;
              MentalPack[8 + nCount].wValue := NewMentalAbility.HP - MentalAbility.HP;
              Inc(nCount);
              Continue;
            end;
            if (sName = 'EF') then begin
              MentalPack[8 + nCount].btType := $0C;
              MentalPack[8 + nCount].wValue := NewMentalAbility.ElementForce - MentalAbility.ElementForce;
              Inc(nCount);
              Continue;
            end;
            if (sName = 'AC') then begin
              MentalPack[8 + nCount].btType := $09;
              MentalPack[8 + nCount].wValue := MakeWord(NewMentalAbility.AC - MentalAbility.AC, NewMentalAbility.AC2 - MentalAbility.AC2);
              Inc(nCount);
              Continue;
            end;
            if (sName = 'MAC') then begin
              MentalPack[8 + nCount].btType := $0A;
              MentalPack[8 + nCount].wValue := MakeWord(NewMentalAbility.MAC - MentalAbility.MAC, NewMentalAbility.MAC2 - MentalAbility.MAC2);
              Inc(nCount);
              Continue;
            end;
            if (sName = 'THUMP') then begin
              MentalPack[8 + nCount].btType := $0B;
              MentalPack[8 + nCount].wValue := NewMentalAbility.Thump - MentalAbility.Thump;
              Inc(nCount);
              Continue;
            end;
            if (sName = 'AGAINST') then begin
              MentalPack[8 + nCount].btType := $0D;
              MentalPack[8 + nCount].wValue := NewMentalAbility.Against - MentalAbility.Against;
              Inc(nCount);
              Continue;
            end;
            if (sName = 'UNPALSY') then begin
              MentalPack[8 + nCount].btType := $0E;
              MentalPack[8 + nCount].wValue := NewMentalAbility.UnPalsy - MentalAbility.UnPalsy;
              Inc(nCount);
              Continue;
            end;
          end;
        finally
          Foresee.free;
        end;
      end else
        nCount := 0;
    end;
    m_defMsg := MakeDefaultMsg(CM_QUERYMENTALABIL, Integer(PlayObject), MakeWord(8, nCount), PlayObject.m_btMentalLevel, 0);
    SendSocket(@m_defMsg, EnCodeBuffer(@MentalPack, SizeOf(TMentalPack) * (8 + nCount)));
  end;
end;

//宠物摆摊

procedure TPlayObject.ClientPetDoShop(nPet: Integer; shopItemCount: word; sMsg: string);
var
  RetCode                               : Integer;
  DoShopResult                          : TDoShopResult;
  i, j, ii                              : Integer;
  UserShop                              : TUserShop;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  boFind                                : Boolean;
  sName, s1C                            : string;
  Castle                                : TUserCastle;
  tm                                    : DWORD;
  Shop                                  : TShop;
  BaseObjectList                        : TList;
  BaseObject                            : TBaseObject;
resourcestring
  sHint1                                = '骑宠状态不能摆摊。';
  sHint2                                = '此地图禁止摆摊。';
  sHint3                                = '正在攻城的区域禁止摆摊。';
  sHint4                                = '你正在进行抢宝活动,禁止摆摊。';
  sHint5                                = '周围没有空的位置,无法摆下你的摊位。';
  sHint6                                = '摆摊物品价格定义错误,请勿使用非法外挂!';
  sHint7                                = '金币交易价格定义超过允许的范围。';
  sHint8                                = '元宝交易价格定义超过允许的范围。';
  sHint9                                = '此物品开启后不允许交易,但时间到后可丢弃。';
  sHint10                               = '你要出售的物品并不存在。';
  sHint11                               = ' 不允许交易。';
begin
  if m_PackPet <> nil then Exit;

  if nPet = Integer(Self) then nPet := Integer(m_Pet);

  if (nPet = 0) or (m_Pet = nil) or (nPet <> Integer(m_Pet)) then Exit;

  {
    if m_boRideOn then begin
      SysMsg(sHint1, c_Red, t_Hint);
      Exit;
    end;
   }
  if not g_Config.boPetDoShop then begin
    SysMsg('当前服务器宠物豹摆摊系统未开放!', c_Red, t_Hint);
    Exit;
  end;

  if not m_boCanDeal then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, g_sCanotTryDealMsg);
    Exit;
  end;

  if m_PEnvir.m_MapFlag.boNoDoShop then begin
    SysMsg(sHint2, c_Red, t_Hint);
    Exit;
  end;

  Castle := g_CastleManager.InCastleWarArea(Self);
  //城堡正在战斗
  if (Castle <> nil) and Castle.m_boUnderWar then begin
    SysMsg(sHint3, c_Red, t_Hint);
    Exit;
  end;
  if m_boArrow then begin
    SysMsg(sHint4, c_Red, t_Hint);
    Exit;
  end;

  BaseObjectList := TList.Create;
  try
    GetMapBaseObjects(m_Pet.m_PEnvir, m_Pet.m_nCurrX, m_Pet.m_nCurrY, 2, BaseObjectList);
    for i := 0 to BaseObjectList.Count - 1 do begin
      BaseObject := TBaseObject(BaseObjectList.Items[i]);
      if (BaseObject.m_btRaceServer = RC_NPC) then begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你离NPC太近了,不能摆摊。');
        Exit;
      end;
    end;
  finally
    BaseObjectList.free;
  end;

  //检查前后左右有没有空位置
  if (shopItemCount > 0) then begin                                                                 //开始摆摊的时候才需要判断
    if (m_Pet.m_nCurrX > 0) and (m_Pet.m_nCurrX < m_PEnvir.m_nWidth) and
      (m_Pet.m_nCurrY > 0) and (m_Pet.m_nCurrY < m_PEnvir.m_nHeight) and
      m_PEnvir.CanWalk(m_Pet.m_nCurrX, m_Pet.m_nCurrY - 1, True) and                                //0  0 -1
      m_PEnvir.CanWalk(m_Pet.m_nCurrX + 1, m_Pet.m_nCurrY - 1, True) and                            //1  1 -1
      m_PEnvir.CanWalk(m_Pet.m_nCurrX + 1, m_Pet.m_nCurrY, True) and                                //2  1  0
      m_PEnvir.CanWalk(m_Pet.m_nCurrX + 1, m_Pet.m_nCurrY + 1, True) and                            //3  1  1
      m_PEnvir.CanWalk(m_Pet.m_nCurrX, m_Pet.m_nCurrY + 1, True) and                                //4  0  1
      m_PEnvir.CanWalk(m_Pet.m_nCurrX - 1, m_Pet.m_nCurrY + 1, True) and                            //5 -1  1
      m_PEnvir.CanWalk(m_Pet.m_nCurrX - 1, m_Pet.m_nCurrY, True) and                                //6 -1  0
      m_PEnvir.CanWalk(m_Pet.m_nCurrX - 1, m_Pet.m_nCurrY - 1, True) then                           //7 -1 -1
    else begin
      SysMsg(sHint5, c_Red, t_Hint);
      Exit;
    end;
  end;

  shopItemCount := _MIN(15, shopItemCount);
  if shopItemCount = 0 then begin
    RetCode := $FF;
  end else begin                                                                                    //判断能否摆摊
    RetCode := 1;
  end;
  FillChar(Shop, SizeOf(TShop), #0);
  if (RetCode = 1) and (shopItemCount > 0) and (sMsg <> '') then begin                              //取摊位名字和物品
    DeCodeBuffer(sMsg, @Shop, SizeOf(TShop));
  end;
  //检测摊位名称
  if CheckFilterWords(Shop.ShopName) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '输入内容含有非法字符!');
    Exit;
  end;
  for i := 0 to shopItemCount - 1 do begin
    if Shop.ShopItems[i].MakeIndex <> 0 then begin
      if not (Shop.ShopItems[i].PayType in [0..1]) then begin
        SysMsg(sHint6, c_Red, t_Hint);
        shopItemCount := 0;
        Exit;
      end;
      if (Shop.ShopItems[i].PayType = 0) and
        ((Shop.ShopItems[i].Price < 1) or (Shop.ShopItems[i].Price > 150000000)) then begin
        SysMsg(sHint7, c_Red, t_Hint);
        shopItemCount := 0;
        Exit;
      end;
      if (Shop.ShopItems[i].PayType = 1) and
        ((Shop.ShopItems[i].Price < 1) or (Shop.ShopItems[i].Price > 10000000)) then begin
        SysMsg(sHint8, c_Red, t_Hint);
        shopItemCount := 0;
        Exit;
      end;

      //检查物品合法性
      boFind := False;
      for j := m_ItemList.Count - 1 downto 0 do begin
        UserItem := pTUserItem(m_ItemList[j]);
        if UserItem.MakeIndex = Shop.ShopItems[i].MakeIndex then begin
          StdItem := UserEngine.GetStdItem(UserItem.wIndex);
          if StdItem = nil then Break;

          sName := '';
          ItemUnit.GetCustomItemName(UserItem, sName);
          {物品控制-禁止摆摊物品}
          if CheckSPCode(StdItem.SPCode, SP_DISABLEDOSHOP) or
            ((UserItem.btItemExt[4] and EX_BIND) = EX_BIND) then begin                              //物品控制-禁止摆摊物品
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sName + sHint11);
            shopItemCount := 0;
            Exit;
          end;
          //魂佑灵兽禁止放入灵犀宝盒
          if (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '魂佑灵兽不允许出售');
            shopItemCount := 0;
            Exit;
          end;
          {已放出豹禁止出售}
          if IsDownPetItem(UserItem.MakeIndex) then begin
            SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sName + '放出宠物时不允许出售');
            shopItemCount := 0;
            Exit;
          end;
          boFind := True;
          Break;
        end;
      end;
      if not boFind then begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, sHint10);
        shopItemCount := 0;
        Exit;
      end;
    end;
  end;
  for i := shopItemCount to 14 do begin
    Shop.ShopItems[i].MakeIndex := 0;
    Shop.ShopItems[i].Price := 0;
    Shop.ShopItems[i].PayType := 0;
  end;
  m_PackPet := g_PetBoothManage.CreatePetObject(m_dwDBIndex, m_Pet, Shop.ShopName);
  if m_PackPet = nil then Exit;
  m_PackPet.SendRefMsg(RM_TURN,
    m_PackPet.m_btDirection,
    m_PackPet.m_nCurrX,
    m_PackPet.m_nCurrY,
    CalcCent(m_PackPet.m_WAbil.dwHP, m_PackPet.m_WAbil.dwMaxHP),
    m_PackPet.GetShowName);

  m_PetInfo[1] := m_PetInfo[0];
  PetHide(m_PetInfo[0].nMakeIndex);

  //把要出售的物品移动到豹子包裹里
  for i := 0 to shopItemCount - 1 do begin
    if Shop.ShopItems[i].MakeIndex <> 0 then begin
      for j := m_ItemList.Count - 1 downto 0 do begin
        UserItem := pTUserItem(m_ItemList[j]);
        if UserItem.MakeIndex = Shop.ShopItems[i].MakeIndex then begin
          if m_PackPet.AddBoothItem(UserItem, @Shop.ShopItems[i]) then begin
            m_ItemList.Delete(j);
            SendDelItems(UserItem);
            WeightChanged;
          end;
          Break;
        end;
      end;
    end;
  end;

  m_nPetTargetX := m_PackPet.m_nCurrX;
  m_nPetTargetY := m_PackPet.m_nCurrY;

  if (RetCode = 0) and ((m_PackPet.m_btDirection mod 2) = 0) then
    m_PackPet.m_btDirection := m_PackPet.m_btDirection + 1;

  m_PackPet.GetUserShop(@UserShop);
  UserShop.DoShopResult.RetCode := RetCode;
  m_PackPet.SaveRcd := True;

  //发送操作结果给本人
  SendDefMessage(34977, 0, 0, 0, 0, '');
  SendDelayMsg(Self, RM_SENDSHOPITEMS, 0, 0, 0, 0, '', 500);                                        // m_PackPet.SendShopItems(Self, 1);

  UserShop.DoShopResult.RetCode := 0;
  UserShop.GoodsCount := 0;

  //广播操作结果
  SendRefMsg(RM_PETDOSHOP,
    m_PackPet.m_btDirection,
    MakeLong(m_PackPet.m_nCurrX, m_PackPet.m_nCurrY),
    RetCode,
    Integer(m_PackPet),
    EnCodeBuffer(@UserShop, 62));
  SendPetInfo($03);
  SysMsg('灵兽守摊开始', c_Red, t_Hint);

  if (not m_boPneuma) then begin
    m_sScriptParam[0] := '1';
    ExecuteScript(g_FunctionNPC, '@开始摆摊');
  end;
end;

procedure TPlayObject.ClientRequestPetDoShop();                                                     //请求摆摊
var
  i, j                                  : Integer;
  UserItem                              : pTUserItem;
  ShopInfo                              : TShopInfo;
begin
  if (m_PackPet = nil) then begin
    SendDefMessage(SM_80D5, Integer(m_Pet), 5, 0, 0, '');
  end else
    SendDefMessage(SM_80D5, Integer(m_PackPet), 5, 1, 0,
      Format('%s(%d:%d)', [m_PackPet.m_PEnvir.m_sMapDesc,
      m_PackPet.m_nCurrX, m_PackPet.m_nCurrY]));
end;

//宠物收摊

procedure TPlayObject.ClientPetStopDoShop();
begin
  if (m_PackPet <> nil) then begin
    m_PackPet.PetStopDoShop();
    m_PackPet := nil;
    m_PetInfo[1].nMakeIndex := 0;
    m_PetInfo[1].wLevel := 0;
    m_PetInfo[1].btType := 0;
    m_PetInfo[1].btReLive := 0;
    SendDefMessage(32981, 0, 0, 0, 0, '');
  end;
end;

//更新宠物摊位物品和名称

procedure TPlayObject.ClientUpdatePetShop(nPet: Integer; nOpCode: Integer; sMsg: string);
begin
  if (m_PackPet = nil) or (nPet <> Integer(m_PackPet)) then Exit;                                   //错误
  if ((m_PackPet.m_PEnvir = m_PEnvir) and
    (abs(m_PackPet.m_nCurrX - m_nCurrX) < 15) and
    (abs(m_PackPet.m_nCurrY - m_nCurrY) < 15)) then
    m_PackPet.UpdatePetShop(Self, nOpCode, sMsg);
end;

//取摆摊物品

procedure TPlayObject.ClientGetbackPetShopItem();
var
  i, j                                  : Integer;
  UserItem                              : pTUserItem;
  ShopInfo                              : TShopInfo;
begin
  if m_boGhost or m_boDeath then Exit;
  ShopInfo := g_PetBoothManage.GetPetInfo(m_dwDBIndex);
  if ShopInfo = nil then begin
    SendDefMessage(32981, Integer(Self), 3, 16, 0, '');
    Exit;
  end;

  if ShopInfo.m_PetMon <> nil then begin
    SendDefMessage(32981, Integer(Self), 3, 19, 0, '');
    Exit;
  end;

  if ShopInfo.Count <= 0 then begin
    SendDefMessage(32981, Integer(Self), 3, 16, 0, '');
    Exit;
  end;
  if g_PetBoothManage.GetUserItem(ShopInfo, Self) = 0 then begin
    SysMsg('物品已放入你的包裹内', c_Red, t_Hint);
    WeightChanged;
    SendDefMessage(32981, Integer(Self), 3, 0, 0, '');
  end else
    SendDefMessage(32981, Integer(Self), 3, 13, 0, '');
end;

procedure TPlayObject.ClientGetbackPetMoney();
var
  btCode                                : byte;
  ShopInfo                              : TShopInfo;
begin
  if m_boGhost or m_boDeath then Exit;
  if m_PackPet <> nil then
    ShopInfo := m_PackPet.ShopInfo
  else
    ShopInfo := g_PetBoothManage.GetPetInfo(m_dwDBIndex);

  if ShopInfo = nil then begin
    SendDefMessage(32981, Integer(Self), 2, 23, 0, '');
    Exit;
  end;

  btCode := g_PetBoothManage.GetUserGold(ShopInfo, Self);
  if btCode = 1 then begin
    SendDefMessage(32981, Integer(Self), 2, 0, 0, '');
  end else begin
    if btCode = 0 then
      SendDefMessage(32981, Integer(Self), 2, 23, 0, '')
    else begin
      if btCode = 2 then begin
        SendDefMessage(32981, Integer(Self), 2, 18, 0, '');
      end else begin
        SendDefMessage(32981, Integer(Self), 2, 13, 0, '');
      end;
    end;
  end;
end;

procedure TPlayObject.SendShopResult();
var
  DoShopResult                          : TDoShopResult;
  UserShop                              : TUserShop;
begin
  //重新发送摊位状态
  if m_wShopItemCount > 0 then
    DoShopResult.RetCode := 0
  else
    DoShopResult.RetCode := $FF;
  DoShopResult.ShopType := m_wShopKind;
  DoShopResult.FlagType := m_btShopBanner;
  DoShopResult.FlagColor := m_nBannerColor;

  m_defMsg := MakeDefaultMsg(SM_DOSHOP, Integer(Self), m_nCurrX, m_nCurrY, m_btDirection);
  SendSocket(@m_defMsg, EnCodeBuffer(@DoShopResult, SizeOf(TDoShopResult)));

  UserShop.DoShopResult.RetCode := DoShopResult.RetCode;
  UserShop.DoShopResult.ShopType := DoShopResult.ShopType;
  UserShop.DoShopResult.FlagType := DoShopResult.FlagType;
  UserShop.DoShopResult.FlagColor := DoShopResult.FlagColor;
  UserShop.GoodsCount := 0;
  UserShop.ShopName := m_Shop.ShopName;

  //发送操作结果和商店名称
  SendRefMsg(RM_DOSHOP,
    m_btDirection,
    MakeLong(m_nCurrX, m_nCurrY),
    DoShopResult.ShopType,
    0,
    EnCodeBuffer(@UserShop, SizeOf(TUserShop) {- SizeOf(TClientItem) * 15}));
end;

function TPlayObject.IsShop(): Boolean;                                                             //是否摆摊
begin
  Result := m_wShopItemCount > 0;
end;

procedure TPlayObject.GetUserShop(const pUserShop: PTUserShop);                                     //取摆摊状态
begin
  pUserShop.DoShopResult.ShopType := m_wShopKind;
  pUserShop.DoShopResult.RetCode := 0;
  pUserShop.DoShopResult.FlagType := m_btShopBanner;
  pUserShop.DoShopResult.FlagColor := m_nBannerColor;
  pUserShop.GoodsCount := 0;
  pUserShop.ShopName := m_Shop.ShopName;
end;

//购买玩家摊位的物品 PlayObject:卖家 nInt:MakeIndex

procedure TPlayObject.ClientBuyShopItem(Play: TBaseObject; sItemName: string; nInt: Integer);
var
  i, j, p                               : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  sName                                 : string;
  boFound                               : Boolean;
  Price                                 : Integer;
  pricetype                             : word;
  nCode                                 : Integer;
  maxGold                               : Int64;
  PlayObject                            : TPlayObject;
  petBooth                              : TPetBoothMonster;
begin
  if (nInt = 0) or (Play = nil) then Exit;
  if m_boGhost or m_boDeath then Exit;

  if Play is TPlayObject then
    PlayObject := Play as TPlayObject
  else if Play is TPetBoothMonster then begin
    petBooth := Play as TPetBoothMonster;
    petBooth.BuyShopItem(Self, sItemName, nInt);
    Exit;
  end else
    Exit;

  boFound := False;
  Price := 0;
  pricetype := 0;
  for i := 0 to PlayObject.m_wShopItemCount - 1 do begin
    if nInt = PlayObject.m_Shop.ShopItems[i].MakeIndex then begin
      boFound := True;
      p := i;
      Price := PlayObject.m_Shop.ShopItems[i].Price;
      pricetype := PlayObject.m_Shop.ShopItems[i].PayType;
      Break;
    end;
  end;
  nCode := 1;
  if not boFound then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你要购买的物品已经被售出了!');
    Exit;
  end;
  //检查有没有钱买
  if (pricetype = 0) and (m_nGold < Price) then begin
    nCode := 3;
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你没有这么多金币!');
    Exit;
  end else if (pricetype = 1) and (m_nGameGold < Price) then begin
    nCode := 3;
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '你没有这么多元宝!');
    Exit;
  end;
  if (pricetype <> 0) and (pricetype <> 1) then begin
    SysMsg('暂不支持该物品的支付方式。', c_Red, t_Hint);
    Exit;
  end;
  //检查卖家是否超过金币或元宝携带数限制
  if (pricetype = 0) then begin
    nCode := 3;
    maxGold := PlayObject.m_nGold + Price;
    if maxGold > g_Config.nHumanMaxGold then begin
      SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
        g_sDealHumanGoldLargeThenLimit);
      Exit;
    end;
  end else if (pricetype = 1) then begin
    nCode := 3;
    maxGold := PlayObject.m_nGameGold + Price;
    if maxGold > g_Config.nHumanMaxGameGold then begin
      SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0,
        g_sDealHumanGameGoldLargeThenLimit);
      Exit;
    end;
  end;

  for i := PlayObject.m_ItemList.Count - 1 downto 0 do begin
    UserItem := PlayObject.m_ItemList.Items[i];
    if (UserItem <> nil) and (UserItem.MakeIndex = nInt) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        //取自定义物品名称
        sName := '';
        ItemUnit.GetCustomItemName(UserItem, sName);

        if (CompareText(sItemName, sName) = 0) then begin
          if (PlayObject <> nil) and
            (PlayObject.m_wShopItemCount > 0) and
            ((PlayObject.m_PEnvir = m_PEnvir) and
            (abs(PlayObject.m_nCurrX - m_nCurrX) < 15) and
            (abs(PlayObject.m_nCurrY - m_nCurrY) < 15)) then begin

            //重量、包裹容量允许
            if IsAddWeightAvailable(StdItem.Weight) then begin

              //添加到包裹
              if AddItemToBag(UserItem) then begin
                //删除包裹物品
                PlayObject.m_ItemList.Delete(i);

                //移动物品
                Dec(PlayObject.m_wShopItemCount);
                for j := p to PlayObject.m_wShopItemCount - 1 do begin
                  PlayObject.m_Shop.ShopItems[j] := PlayObject.m_Shop.ShopItems[j + 1];
                end;

                if pricetype = 0 then begin
                  //给卖物所得
                  PlayObject.IncGold(Price);
                  PlayObject.GoldChanged;
                  //减买物消费
                  DecGold(Price);
                  GoldChanged;
                end else if pricetype = 1 then begin
                  //给卖物所得
                  Inc(PlayObject.m_nGameGold, Price);
                  PlayObject.GameGoldChanged;
                  //减买物消费
                  Dec(m_nGameGold, Price);
                  GameGoldChanged;
                end;

                SendAddItem(UserItem);
                nCode := 0;

                //发送刷新后的摊位信息,
                PlayObject.SendShopResult();

                {清除自定义物品名称}//是否有必要????
                if UserItem.btValue[13] and $01 = 1 then begin
                  ItemUnit.DelCustomItemName(UserItem.MakeIndex, UserItem.wIndex);
                  UserItem.btValue[13] := UserItem.btValue[13] and $FE;
                end;

                m_dwSaveRcdTick := 0;
                //发送删除物品的数据包
                PlayObject.SendDelItems(UserItem);

                UserEngine.SaveHumanRcd(PlayObject);
                PlayObject.m_dwSaveRcdTick := GetTickCount;
              end else
                nCode := 2;
            end else
              SysMsg(g_sCanotGetItems, c_Red, t_Hint);
          end;
        end;
      end;
      Break;
    end;
  end;

  // for
  if nCode = 0 then begin
    SendMsg(Self, RM_BUYITEM_SUCCESS, 0, m_nGold, nInt, 0, '');
    SysMsg('你购买了' + sName, c_Red, t_Hint);
    PlayObject.SendShopItems(Self, 2);
    if PlayObject.m_btRaceServer = RC_PLAYOBJECT then begin
      if pricetype = 0 then
        PlayObject.SysMsg(m_sCharName + '在' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Date + Time) + '以' + IntToStr(Price) + '个金币购买了你的' + sName, c_Red, t_Hint)
      else
        PlayObject.SysMsg(m_sCharName + '在' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Date + Time) + '以' + IntToStr(Price) + '个元宝购买了你的' + sName, c_Red, t_Hint);
    end;

    if (UserItem <> nil) and (StdItem <> nil) then begin
      if not IsCheapStuff(StdItem.StdMode) then begin
        if StdItem.boGameLog = 1 then
          AddGameDataLog('37' + #9 +
            m_sMapName + #9 +
            IntToStr(m_nCurrX) + #9 +
            IntToStr(m_nCurrY) + #9 +
            PlayObject.m_sCharName + #9 +
            StdItem.Name + #9 +
            IntToStr(UserItem.MakeIndex) + #9 +
            '1' + #9 +
            m_sCharName);
      end;
    end;

    if pricetype = 0 then begin
      if g_boGameLogGold then
        AddGameDataLog('14' + #9 +
          m_sMapName + #9 +
          IntToStr(m_nCurrX) + #9 +
          IntToStr(m_nCurrY) + #9 +
          m_sCharName + #9 +
          sSTRING_GOLDNAME + #9 +
          IntToStr(m_nGold) + #9 +
          '1' + #9 +
          PlayObject.m_sCharName);
    end else begin
      if g_boGameLogGameGold then
        AddGameDataLog('17' + #9 +
          m_sMapName + #9 +
          IntToStr(m_nCurrX) + #9 +
          IntToStr(m_nCurrY) + #9 +
          m_sCharName + #9 +
          sSTRING_GAMEGOLDNAME + #9 +
          IntToStr(m_nGameGold) + #9 +
          '2' + #9 +
          PlayObject.m_sCharName);

    end;
  end else begin
    SendMsg(Self, RM_BUYITEM_FAIL, 0, nCode, 0, 0, '');
  end;
end;

procedure TPlayObject.SendAddPetSoulInfo(nMakeIndex: Integer);
var
  boFind                                : Boolean;
  i, ii                                 : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  for ii := 0 to 7 do begin
    boFind := False;
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList.Items[i];
      if (UserItem.MakeIndex = m_SoulPetItemIndex[ii]) then begin
        boFind := True;
        Break;
      end;
    end;
    if not boFind then begin
      m_SoulPetItemIndex[ii] := nMakeIndex;
      g_SmallPacketManage.Init();
      g_SmallPacketManage.WriteInteger(nMakeIndex);
      g_SmallPacketManage.WriteWord(ii);
      g_SmallPacketManage.FillWrite(64, 0);
      m_defMsg := MakeDefaultMsg(SM_ADDSOULPET, Integer(Self), 0, 0, 0);
      SendSocket(@m_defMsg, g_SmallPacketManage.GetMsg);
      Break;
    end;
  end;
end;

//发送魂佑灵兽信息

procedure TPlayObject.ClientQueryPetSoulInfo;
var
  i, ii, nCount                         : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  MagicList                             : array[0..40] of byte;
  btID, btLv                            : byte;
begin
  nCount := 0;
  FillChar(m_SoulPetItemIndex, SizeOf(m_SoulPetItemIndex), #0);
  g_LargePacketManage.Init();
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if (StdItem <> nil) and (StdItem.StdMode = 49) and (StdItem.Shape = 51) and (UserItem.btItemExt[29] >= 2) then begin
      g_LargePacketManage.WriteInteger(UserItem.MakeIndex);
      g_LargePacketManage.WriteWord(nCount);
      FillChar(MagicList, 41, 0);
      //写入技能信息
      for ii := 0 to 9 do begin
        btID := UserItem.btExtra.PetMagics[ii].GetID();
        btLv := UserItem.btExtra.PetMagics[ii].GetLv();
        if (btID in [0..40]) and (btLv > 0) then begin
          MagicList[btID] := (btLv shl 4) or (ii and $0F);
        end;
      end;
      g_LargePacketManage.WriteBuffer(MagicList[0], 41);
      //23个技能位没有用到,写0
      g_LargePacketManage.FillWrite(23, 0);
      m_SoulPetItemIndex[nCount] := UserItem.MakeIndex;
      Inc(nCount);
    end;
    if nCount >= 8 then Break;
  end;

  if nCount > 0 then begin
    m_defMsg := MakeDefaultMsg(SM_QUERYPETSOUL, Integer(Self), nCount, 0, 0);
    SendSocket(@m_defMsg, g_LargePacketManage.GetMsg);
  end;
end;

//发送魂佑灵兽装备

procedure TPlayObject.ClientQueryPetSoulItem(nMakeIndex: Integer; wIndex: word);
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnQueryPetSoulItem(Self, nMakeIndex, wIndex);
  except
    MainOutMessage(Format('TPlayObject::OnQueryPetSoulItem SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

//查询人物属性

procedure TPlayObject.ClientQueryAbility();
begin
  if Assigned(m_VersionManage) then
  try


    m_VersionManage.OnQueryAbility(Self);
  except
    MainOutMessage(Format('TPlayObject::OnQueryAbility SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

function TPlayObject.GetPetSoulItem(const nMakeIndex: Integer; boNew: Boolean = False): pTPetSoulItem;
var
  PetSoulItems                          : pTPetSoulItem;
  i                                     : Integer;
begin
  Result := nil;
  PetSoulItems := nil;
  for i := 0 to m_PetSoulItemsList.Count - 1 do begin
    PetSoulItems := pTPetSoulItem(m_PetSoulItemsList.Items[i]);
    if (PetSoulItems^.nMakeIndex = nMakeIndex) then begin                                           //跟随的灵兽
      Result := PetSoulItems;
      Break;
    end;
  end;

  if (Result = nil) and boNew then begin
    New(Result);
    FillChar(Result^, SizeOf(TPetSoulItem), 0);
    Result^.nMakeIndex := nMakeIndex;
    m_PetSoulItemsList.Add(Result);
  end;

end;

//计算魂佑灵兽装备的属性

procedure TPlayObject.RecalcPetSoulAbilitys;
resourcestring
  sExceptionMsg                         = '[Exception] TPlayObject::RecalcPetSoulAbilitys Name=%s Code=%d';
const
  nMax                                  : array[1..9] of Integer = (2, 4, 6, 4, 6, 4, 6, 4, 6);
var
  btMagicID                             : byte;
  i, nWhere                             : Integer;
  PetSoulItems                          : pTPetSoulItem;
  StdItem                               : pTStdItem;
  StdItem18                             : TStdItem;
  UserItem                              : TUserItem;
  nPetItemCount                         : array[1..9] of Integer;
  nCheckCode                            : Integer;
begin
  nCheckCode := 0;
  try
    m_FelementReduce := 0;
    m_FelementRedouble := 0;
    m_ReduceSkillRate := 0;
    FillChar(m_ReduceSkillPoint, SizeOf(m_ReduceSkillPoint), #0);

    nCheckCode := 1;

    if (not m_boBeast) or (m_PetInfo[5].nMakeIndex = 0) or m_boPneuma then Exit;

    nCheckCode := 2;

    PetSoulItems := GetPetSoulItem(m_PetInfo[5].nMakeIndex, True);
    if PetSoulItems = nil then Exit;
    nCheckCode := 3;

    for i := 1 to 9 do begin
      nPetItemCount[i] := 0;
    end;
    nCheckCode := 4;
    for nWhere := Low(PetSoulItems^.Items) to High(PetSoulItems^.Items) do begin
      UserItem := PetSoulItems^.Items[nWhere];
      nCheckCode := 5;
      if UserItem.wIndex > 0 then begin
        StdItem := UserEngine.GetStdItem(UserItem.wIndex);
        if StdItem <> nil then begin
          StdItem18 := StdItem^;
          nCheckCode := 6;
          ItemUnit.GetItemAddValue(@UserItem, StdItem18);
          m_FelementRedouble := _MIN(High(word), m_FelementRedouble + LoWord(StdItem18.DC));        //五行攻击
          m_FelementReduce := _MIN(High(word), m_FelementReduce + LoWord(StdItem18.AC));            //五行防御
          nCheckCode := 7;
          btMagicID := UserItem.btItemExt[14];                                                      //抵抗技能ID
          for i := 0 to 40 do begin
            if (btMagicID = g_BeastMagic[i].wSkillID) then begin
              m_ReduceSkillPoint[i] := _MIN(High(byte), m_ReduceSkillPoint[i] + HiWord(StdItem18.MC)); //抵抗技能伤害
              Break;
            end;
          end;
          nCheckCode := 8;
          if StdItem.Shape in [1..9] then Inc(nPetItemCount[StdItem.Shape]);
        end;
      end;
    end;
    nCheckCode := 9;
    //装备数量激活抵抗技能几率
    for i := 1 to 9 do begin
      if (nPetItemCount[i] > nMax[i]) then begin
        m_ReduceSkillRate := _MIN(10, m_ReduceSkillRate + i + 1);                                   //几率最高为10
      end;
    end;
  except
    on E: Exception do
      MainOutMessage(Format(sExceptionMsg, [m_sCharName, nCheckCode]));
  end;
end;

//穿戴灵兽装备

procedure TPlayObject.ClientTakeOnPetSoulItem(nWhere, nMakeIndex: Integer; wIndex: word);
var
  n18, n14, i                           : Integer;
  StdItem                               : pTStdItem;
  UserItem, TakeoffItem                 : pTUserItem;
  sName                                 : string;
  StdItem18                             : TStdItem;
  PetSoulItems                          : pTPetSoulItem;
  btReLive, btLevel                     : byte;
label
  FailExit;
begin
  if m_boPneuma or m_boGhost or m_boDeath then Exit;

  if not (wIndex in [0..7]) then Exit;

  if (m_PetInfo[0].nMakeIndex <> m_SoulPetItemIndex[wIndex]) and ((m_PetInfo[5].nMakeIndex <> m_SoulPetItemIndex[wIndex])) then begin
    n18 := -1;
    goto FailExit;
  end;

  PetSoulItems := GetPetSoulItem(m_SoulPetItemIndex[wIndex], True);
  if PetSoulItems = nil then begin
    n18 := -1;
    goto FailExit;
  end;

  StdItem := nil;
  UserItem := nil;
  n14 := -1;
  n18 := 0;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];                                                                //包裹里的物品
    if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if StdItem <> nil then begin
        n14 := i;
        Break;
      end;
    end;
    UserItem := nil;
  end;

  if (m_SoulPetItemIndex[wIndex] = m_PetInfo[0].nMakeIndex) then begin
    btReLive := m_PetInfo[0].btReLive;
    btLevel := m_PetInfo[0].wLevel;
  end else begin
    btReLive := m_PetInfo[5].btReLive;
    btLevel := m_PetInfo[5].wLevel;
  end;

  if (StdItem <> nil) and (UserItem <> nil) then begin
    if CheckPetUserItems(nWhere, StdItem) then begin
      StdItem18 := StdItem^;
      if (btReLive < 3) and (btLevel < StdItem18.NeedLevel) then begin
        SysMsg('灵兽等级不满足条件,无法佩戴。', c_Red, t_Hint);
        n18 := -1;
        goto FailExit;
      end;

      TakeoffItem := nil;
      if nWhere in [0..5] then begin
        //取下物品
        if PetSoulItems^.Items[nWhere].wIndex > 0 then begin
          New(TakeoffItem);
          TakeoffItem^ := PetSoulItems^.Items[nWhere];
        end;
        PetSoulItems^.Items[nWhere] := UserItem^;
        DelBagItem(n14);
        if TakeoffItem <> nil then begin
          AddItemToBag(TakeoffItem);
          SendAddItem(TakeoffItem);
        end;
        n18 := 1;
        SendDefMessage(SM_TAKEPETSOULITEM, 0, MakeWord(1, 1), wIndex, 0, '');
        RecalcPetSoulAbilitys;
        RecalcAbilitys();                                                                           //重新计算属性
        SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
        SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
      end;
    end;
  end;

  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEPETSOULITEM, 0, MakeWord(1, 0), wIndex, 0, '');
end;

procedure TPlayObject.ClientTakeOffPetSoulItem(nWhere, nMakeIndex: Integer; wIndex: word);
var
  i, n18                                : Integer;
  StdItem                               : pTStdItem;
  UserItem                              : pTUserItem;
  PetSoulItems                          : pTPetSoulItem;
label
  FailExit;
begin
  if m_boPneuma or m_boGhost or m_boDeath then Exit;

  if not (wIndex in [0..7]) then Exit;

  if (m_PetInfo[0].nMakeIndex <> m_SoulPetItemIndex[wIndex]) and ((m_PetInfo[5].nMakeIndex <> m_SoulPetItemIndex[wIndex])) then begin
    n18 := -1;
    goto FailExit;
  end;

  PetSoulItems := GetPetSoulItem(m_SoulPetItemIndex[wIndex], False);
  if PetSoulItems = nil then begin
    n18 := -1;
    goto FailExit;
  end;

  n18 := 0;
  if nWhere in [0..5] then begin
    if PetSoulItems^.Items[nWhere].wIndex > 0 then begin
      if PetSoulItems^.Items[nWhere].MakeIndex = nMakeIndex then begin
        StdItem := UserEngine.GetStdItem(PetSoulItems^.Items[nWhere].wIndex);
        if (StdItem <> nil) then begin
          New(UserItem);
          UserItem^ := PetSoulItems^.Items[nWhere];
          if AddItemToBag(UserItem) then begin
            PetSoulItems.Items[nWhere].wIndex := 0;
            SendAddItem(UserItem);
            SendDefMessage(SM_TAKEPETSOULITEM, 0, MakeWord(2, 1), wIndex, 0, '');

            RecalcPetSoulAbilitys;
            RecalcAbilitys();                                                                       //重新计算属性
            SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
            SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
            n18 := 1;
          end else begin
            Dispose(UserItem);
            n18 := -1;
          end;
        end;
      end;
    end;
  end;

  FailExit:
  if n18 <= 0 then
    SendDefMessage(SM_TAKEPETSOULITEM, 0, MakeWord(2, 0), wIndex, 0, '');
end;

procedure TPlayObject.RecalcPerHealthSpell();
var
  nPerReply                             : Integer;
begin
  inherited RecalcPerHealthSpell();
  nPerReply := m_nAllIncReply div 10;
  Inc(m_nPerHealth, nPerReply);
  Inc(m_nPerSpell, nPerReply);
end;

//兽化

procedure TPlayObject.ClientMagOfPetBeast(nMakeIndex: Integer);
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  i                                     : Integer;
  btID, btLv                            : byte;
begin
  if m_MagicSkills[SKILL_BEAST] = nil then Exit;

  //先判断 nMakeIndex 的合法性
  StdItem := nil;
  for i := 0 to m_ItemList.Count - 1 do begin                                                       //包裹里的物品
    UserItem := m_ItemList.Items[i];
    StdItem := nil;
    if (UserItem <> nil) and (UserItem.MakeIndex = nMakeIndex) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      Break;
    end;
  end;

  if (StdItem <> nil) and (UserItem <> nil) and
    (StdItem.StdMode = 49) and (StdItem.Shape = 51) and
    (UserItem.btItemExt[29] in [2, 3]) then begin

    if m_boBeast then begin
      m_boBeast := False;
      m_PetInfo[5].nMakeIndex := 0;
      m_PetInfo[5].wLevel := 0;
      m_PetInfo[5].btType := 0;
      m_PetInfo[5].btReLive := 0;

      UserItem.btItemExt[29] := 2;
      SendUpdateItem(UserItem, False);

      SendDefMessage(SM_PETBAGSIZE, Integer(Self), 0, m_nPetShopSize, m_nPetBagSize, '');
      m_defMsg := MakeDefaultMsg(34977, 0, 100, 0, 0);
      SendSocket(@m_defMsg, EnCodeBuffer(@nMakeIndex, 4));

      SendRefMsg(RM_510, 1, 0, 171, 0, '');
      //SysMsg('附体魂佑灵兽已经收回到包裹中,魂佑附体状态解除!', c_Red, t_Hint);
    end else begin
      if (m_Pet <> nil) and (m_PetInfo[0].nMakeIndex <> 0) then begin
        m_boBeast := True;
        for i := 0 to 9 do begin
          btID := UserItem.btExtra.PetMagics[i].GetID();
          btLv := UserItem.btExtra.PetMagics[i].GetLv();
          if (btID in [0..40]) and (btLv > 0) then begin
            m_ReduceSkillLevel[btID] := btLv;
          end;
        end;
        UserItem.btItemExt[29] := 3;
        SendUpdateItem(UserItem, False);
        SendRefMsg(RM_510, 1, 0, 170, 0, '');
        m_PetInfo[5] := m_PetInfo[0];
        SendPetInfo($0A);

        m_nCharStatus := GetCharStatus();
        StatusChanged();

        g_SmallPacketManage.Init;
        g_SmallPacketManage.WriteWord(m_nCurrY);
        g_SmallPacketManage.WriteWord(m_Pet.m_nCurrX);
        g_SmallPacketManage.WriteWord(m_Pet.m_nCurrY);
        SendRefMsg(RM_PETBEAST, m_nCurrX, Integer(m_Pet), 0, 0, g_SmallPacketManage.GetMsg);
        //SysMsg('魂佑灵兽化为魂佑,附体于你!你感觉力量无穷!', c_Red, t_Hint);
        PetHide(m_PetInfo[0].nMakeIndex);
      end else begin
        SysMsg('需要魂佑灵兽处于跟随状态,才能使用兽化技能', c_Red, t_Hint);
        Exit;
      end;
    end;
    RecalcPetSoulAbilitys;
    RecalcAbilitys();                                                                               //重新计算属性
    SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
    SendMsg(Self, RM_SUBABILITY, 0, 0, 0, 0, '');
  end;
end;

function TPlayObject.GetAchievementInfo(const wIndex: word): PTAchievementInfo;
var
  pAchievementInfo                      : PTAchievementInfo;
  i                                     : Integer;
begin
  Result := nil;
  pAchievementInfo := nil;
  for i := 0 to m_AchievementList.Count - 1 do begin
    pAchievementInfo := PTAchievementInfo(m_AchievementList.Items[i]);
    if (pAchievementInfo^.wIndex = wIndex) then begin
      Result := pAchievementInfo;
      Break;
    end;
  end;
end;

procedure TPlayObject.SendWenPeiJH();                                                               //发送纹佩精华
begin
  if m_dwWenPeiJH = 0 then Exit;
  m_defMsg := MakeDefaultMsg(SM_WENPEIJH, Integer(Self), m_dwWenPeiJH, 0, 0);
  SendSocket(@m_defMsg, '');
end;

{-------------------------------------------------------------------------------
  过程名:    TPlayObject.ClientAchievementSystem
  作者:      Cloud
  日期:      2013.03.17
  参数:      boWenPei 是否发送纹佩宝盒的列表给客户端
  返回值:    无
-------------------------------------------------------------------------------}

procedure TPlayObject.ClientAchievementSystem(boWenPei: Boolean = False);                           //成就系统
var
  AchievementSystem                     : TClientAchievementInfo;
  pAchievementInfo                      : PTAchievementInfo;
  i                                     : Integer;
  sWenPeiBox                            : string;
  XmlAchievement                        : PTXmlAchievement;
begin
  if m_boPneuma then Exit;
  if m_boGhost or m_boDeath then Exit;
  if m_AchievementList.Count = 0 then Exit;

  g_LargePacketManage.Init();                                                                       //从0位开始写
  m_wAchievePoint := 0;
  for i := 0 to m_AchievementList.Count - 1 do begin
    pAchievementInfo := PTAchievementInfo(m_AchievementList.Items[i]);
    XmlAchievement := GetXmlAchievement(pAchievementInfo^.wIndex);
    if XmlAchievement = nil then
      Continue;

    if (pAchievementInfo^.tData > 0) then
      Inc(m_wAchievePoint);

    AchievementSystem.dwData := 0;
    if pAchievementInfo^.tData <> 0 then
      AchievementSystem.dwData := DateTimeToWolTIme(pAchievementInfo^.tData);

    AchievementSystem.wIndex := pAchievementInfo^.wIndex;
    AchievementSystem.wStep := pAchievementInfo^.wStep;
    AchievementSystem.btprize := XmlAchievement^.btprize;
    AchievementSystem.dwprizeValue := XmlAchievement^.dwprizeValue;
    g_LargePacketManage.WriteBuffer(AchievementSystem, SizeOf(TClientAchievementInfo));             //写入成就
  end;

  if boWenPei then begin
    sWenPeiBox := '';
    for i := Low(m_WenPeiBox) to High(m_WenPeiBox) do begin
      if m_WenPeiBox[i] <> 0 then
        sWenPeiBox := sWenPeiBox + '|' + IntToStr(m_WenPeiBox[i])
      else
        Break;
    end;
    m_defMsg := MakeDefaultMsg(SM_WENPEIBOX, Integer(Self), Length(sWenPeiBox), m_wAchievePoint, 0);
    SendSocket(@m_defMsg, EnCodeString(sWenPeiBox));
  end;

  m_defMsg := MakeDefaultMsg(SM_ACHIEVEMENTLIST, 0, m_AchievementList.Count, 0, 0);
  SendSocket(@m_defMsg, g_LargePacketManage.GetMsg());
end;

{-------------------------------------------------------------------------------
  过程名:    TPlayObject.ClientMakeWenPei
  作者:      Cloud
  日期:      2013.03.17
  参数:      btZW=主纹  btJW=精纹 btDW=底纹 btBW=边纹
  返回值:    无
-------------------------------------------------------------------------------}

procedure TPlayObject.ClientMakeWenPei(btZW, btJW, btDW, btBW: byte);
  function DelWens(): Integer;
  var
    i, j, ii                            : Integer;
    WenPei                              : array[0..3] of byte;
    nWen                                : Integer;
    boHave                              : Boolean;
  begin
    Result := -1;
    nWen := 0;
    for i := Low(m_WenPeiBox) to High(m_WenPeiBox) do begin
      if m_WenPeiBox[i] <> 0 then
        nWen := i
      else
        Break;
    end;

    WenPei[0] := btZW;
    WenPei[1] := btJW;
    WenPei[2] := btDW;
    WenPei[3] := btBW;
    ii := 0;
    for i := 0 to 3 do begin
      boHave := False;
      for j := 0 to nWen do begin
        if m_WenPeiBox[j] = WenPei[i] then begin
          WenPei[i] := j;
          Inc(ii);
          boHave := True;
          Break;
        end;
      end;
      if not boHave then begin
        Result := i + 1;
        Exit;
      end;
    end;
    if ii = 4 then begin
      for i := 0 to 3 do begin
        m_WenPeiBox[WenPei[i]] := 0;
      end;

      i := 0;
      for j := 0 to nWen do begin
        if m_WenPeiBox[j] <> 0 then begin
          m_WenPeiBox[i] := m_WenPeiBox[j];
          Inc(i);
        end;
      end;

      for i := nWen - 3 to nWen do begin
        m_WenPeiBox[i] := 0;
      end;
      Result := 0;
    end;
  end;
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nResult                               : Integer;
  sError                                : string;
begin
  if m_boPneuma then Exit;
  if m_boGhost or m_boDeath then Exit;
  if (btZW = 0) or (btJW = 0) or (btDW = 0) or (btBW = 0) then
    Exit;
  if (btZW > 255) or (btJW > 255) or (btDW > 255) or (btBW > 255) then
    Exit;
  if m_ItemList.Count < m_nBagSize then begin
    nResult := DelWens();
    if nResult = 0 then begin
      New(UserItem);
      if UserEngine.CopyToUserItemFromName('三界纹佩', UserItem) then begin
        UserItem.btItemExt[4] := 1;                                                                 // 三界纹佩 必须绑定
        UserItem.btItemExt[16] := btZW;                                                             // 主纹
        UserItem.btItemExt[17] := btJW;                                                             // 精纹
        UserItem.btItemExt[18] := btDW;                                                             // 底纹
        UserItem.btItemExt[19] := btBW;                                                             // 边纹
        UserItem.btItemExt[20] := 0;                                                                // 星级

        //主纹 加属性
        UserItem.btItemExt[21] := g_Config.WenPeiList[btZW].btType;
        UserItem.btItemExt[22] := g_Config.WenPeiList[btZW].btValue;
        Inc(UserItem.btItemExt[31], g_Config.WenPeiList[btZW].btAbsorb);
        //精纹  加属性
        UserItem.btItemExt[23] := g_Config.WenPeiList[btJW].btType;
        UserItem.btItemExt[24] := g_Config.WenPeiList[btJW].btValue;
        Inc(UserItem.btItemExt[31], g_Config.WenPeiList[btJW].btAbsorb);
        //底纹  加属性
        UserItem.btItemExt[25] := g_Config.WenPeiList[btDW].btType;
        UserItem.btItemExt[26] := g_Config.WenPeiList[btDW].btValue;
        Inc(UserItem.btItemExt[31], g_Config.WenPeiList[btDW].btAbsorb);
        //边纹  加属性
        UserItem.btItemExt[27] := g_Config.WenPeiList[btBW].btType;
        UserItem.btItemExt[28] := g_Config.WenPeiList[btBW].btValue;
        Inc(UserItem.btItemExt[31], g_Config.WenPeiList[btBW].btAbsorb);

        UserItem.btItemExt[29] := 0;                                                                // 五行强化的百分比
        UserItem.btItemExt[30] := 0;                                                                // 强化后的五行吸收

        m_ItemList.Add((UserItem));
        SendAddItem(UserItem);
        WeightChanged();
        SendDefMessage(SM_TASKWEN, Integer(Self), btZW, 0, 0, '');                                  //通知客户端删除主纹
        SendDefMessage(SM_TASKWEN, Integer(Self), btJW, 0, 0, '');                                  //通知客户端删除精纹
        SendDefMessage(SM_TASKWEN, Integer(Self), btDW, 0, 0, '');                                  //通知客户端删除底纹
        SendDefMessage(SM_TASKWEN, Integer(Self), btBW, 0, 0, '');                                  //通知客户端删除边纹

        SendDefMessage(SM_MAKEWENPEI_SUCCESS, Integer(Self), MakeWord(btZW, btJW), MakeWord(btDW, btBW), 0, '');
        SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '合成成功,纹佩已经放入你的包裹中!');

        StdItem := UserEngine.GetStdItem(UserItem.wIndex);

        if StdItem.boGameLog = 1 then
          AddGameDataLog('9' + #9 +
            m_sMapName + #9 +
            IntToStr(m_nCurrX) + #9 +
            IntToStr(m_nCurrY) + #9 +
            m_sCharName + #9 +
            '三界纹佩' + #9 +
            IntToStr(UserItem.MakeIndex) + #9 +
            '1' + #9 +
            m_sCharName);

      end else begin
        Dispose(UserItem);
        SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '合成失败,三界纹佩不存在数据库!');
      end;
    end else begin
      case nResult of
        1: sError := '存在非法的纹佩组件(主纹)';
        2: sError := '存在非法的纹佩组件(精纹)';
        3: sError := '存在非法的纹佩组件(底纹)';
        4: sError := '存在非法的纹佩组件(边纹)';
      end;
      SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '合成失败,' + sError);
      SysMsg(sError, c_Red, t_Hint);
    end;
  end else begin
    SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '合成失败,包裹必须要有一个空位!');
  end;
end;

//取强化纹佩需要精化

function GetQFWenPeiDemandJF(const UserItem: pTUserItem): Integer;
begin
  Result := 100;
  if UserItem.btItemExt[20] > 0 then
    Result := UserItem.btItemExt[20] * 300;
end;

//取拆解纹佩需要灵力

function GetCJWenPeiDemandLL(const UserItem: pTUserItem): Integer;
var
  eRate                                 : Single;
begin
  Result := 0;
  if UserItem.btItemExt[29] > 0 then begin
    eRate := UserItem.btItemExt[29] / 100;
    Inc(Result, Trunc(UserItem.btItemExt[22] * eRate));
    Inc(Result, Trunc(UserItem.btItemExt[24] * eRate));
    Inc(Result, Trunc(UserItem.btItemExt[26] * eRate));
    Inc(Result, Trunc(UserItem.btItemExt[28] * eRate));
    Inc(Result, Trunc(UserItem.btItemExt[31] * (UserItem.btItemExt[30] / 100)));
  end;
end;

{-------------------------------------------------------------------------------
  过程名:    TPlayObject.ClientGetWenPeiDemand  //查询 强化 或 拆解纹佩 的需求
  作者:      Cloud
  日期:      2013.03.17
  参数:      nMakeIndex=物品Index  nCode= 0强化 1拆解
  返回值:    无
-------------------------------------------------------------------------------}

procedure TPlayObject.ClientGetWenPeiDemand(nMakeIndex, nCode: Integer);
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  nQF, nCJ                              : Integer;
begin
  if m_boPneuma then Exit;
  if m_boGhost or m_boDeath then Exit;
  if nMakeIndex = 0 then Exit;
  if GetUserItemByMakeIndex(nMakeIndex, UserItem) <> -1 then begin
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem.StdMode = 111 then begin
      nQF := 0;
      nCJ := 0;
      if (nCode = 0) then begin                                                                     //强化
        if UserItem.btItemExt[20] >= 10 then begin
          nQF := 0;
        end else begin
          nQF := GetQFWenPeiDemandJF(UserItem);
        end;
      end;

      if (nCode = 1) then begin                                                                     //拆解
        nCJ := GetCJWenPeiDemandLL(UserItem);
      end;

      SendDefMessage(SM_GETWENPEI_DEMAND, Integer(Self), nQF, nCJ, nCode, '');
    end;
  end else begin

  end;
end;

{-------------------------------------------------------------------------------
  过程名:    TPlayObject.ClientTakeWenPei  强化 或 拆解 纹佩
  作者:      Cloud
  日期:      2013.03.17
  参数:      nMakeIndex=物品Index  nCode= 0强化 1拆解
  返回值:    无
-------------------------------------------------------------------------------}

procedure TPlayObject.ClientTakeWenPei(nMakeIndex, nCode: Integer);
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  i, ii, nQF, nCJ, nWen                 : Integer;
  eRate                                 : Single;
begin
  if m_boPneuma then Exit;
  if m_boGhost or m_boDeath then Exit;
  if nMakeIndex = 0 then Exit;
  if GetUserItemByMakeIndex(nMakeIndex, UserItem) <> -1 then begin
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem.StdMode = 111 then begin
      nQF := 0;
      nCJ := 0;
      if nCode = 0 then begin                                                                       //强化
        if UserItem.btItemExt[20] < 10 then begin
          nQF := GetQFWenPeiDemandJF(UserItem);
          if m_dwWenPeiJH >= nQF then begin
            if nQF > 0 then begin
              Dec(m_dwWenPeiJH, nQF);
              SendWenPeiJH();
            end;
            SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '您的纹佩强化成功!');
            Inc(UserItem.btItemExt[20], 1);
            case UserItem.btItemExt[20] of
              01: UserItem.btItemExt[29] := 10;
              02: UserItem.btItemExt[29] := 20;
              03: UserItem.btItemExt[29] := 30;
              04: UserItem.btItemExt[29] := 50;
              05: UserItem.btItemExt[29] := 70;
              06: UserItem.btItemExt[29] := 90;
              07: UserItem.btItemExt[29] := 110;
              08: UserItem.btItemExt[29] := 140;
              09: UserItem.btItemExt[29] := 170;
              10: UserItem.btItemExt[29] := 200;
            end;
            UserItem.btItemExt[30] := Trunc(UserItem.btItemExt[20] * 1.4);
            SendUpdateItem(UserItem);
            ClientGetWenPeiDemand(nMakeIndex, 0);
          end else begin
            SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '您的纹佩精华不足!');
          end;
        end else begin
          SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '您的纹佩以达到强化最大等级!');
        end;
      end else if nCode = 1 then begin                                                              //拆解
        nCJ := GetCJWenPeiDemandLL(UserItem);
        if m_Abil.wNimBusPoint >= nCJ then begin
          nWen := -1;
          for i := Low(m_WenPeiBox) to High(m_WenPeiBox) do begin
            if m_WenPeiBox[i] = 0 then begin
              nWen := i;
              Break;
            end;
          end;
          if (nWen <> -1) and ((nWen + 3) <= 99) then begin
            if nCJ > 0 then begin
              Dec(m_Abil.wNimBusPoint, nCJ);
              RecalcAbilitys();
              SendMsg(Self, RM_ABILITY, 0, 0, 0, 0, '');
            end;
            nQF := 0;
            if UserItem.btItemExt[20] > 0 then begin
              nQF := 100;
              for i := 1 to UserItem.btItemExt[20] - 1 do
                nQF := nQF + i * 300;
            end;
            Inc(m_dwWenPeiJH, nQF);
            SendWenPeiJH();
            ii := 16;
            for i := nWen to nWen + 3 do begin
              m_WenPeiBox[i] := UserItem^.btItemExt[ii];
              Inc(ii);
              SendDefMessage(SM_TASKWEN, Integer(Self), MakeWord(m_WenPeiBox[i], 1), 0, 0, '');
            end;

            SendDelItems(UserItem);
            DelBagItem(UserItem^.MakeIndex, '');

            SendDefMessage(SM_ACHIEVEMENT__OK, Integer(Self), 0, 0, 0, '');
            SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '拆卸成功,纹佩部件和纹佩精华已放回纹佩宝盒!');
          end else begin
            SendDefMessage(SM_ACHIEVEMENT__OK, Integer(Self), 0, 1, 0, '');
          end;
        end else begin
          SendDefMessage(SM_INFORMATION, 0, 0, 0, 0, '您的灵力值不够!');
          SendDefMessage(SM_ACHIEVEMENT__OK, Integer(Self), 0, 1, 0, '');
        end;

      end;
    end;
  end else begin

  end;
end;

{-------------------------------------------------------------------------------
  过程名:    TPlayObject.ClientCollectSuits  成就之收集套装
  作者:      Cloud
  日期:      2013.03.17
  参数:      nCJIdx = 要做的套装成就  nCount=套装组件数量  sData 选择的套装组件索引
  返回值:    无
-------------------------------------------------------------------------------}

procedure TPlayObject.ClientCollectSuits(nCJIdx, nCount: Integer; sData: string);
var
  UserItem                              : pTUserItem;
  nMakeIndexs                           : array[0..7] of DWORD;
  i                                     : Integer;
  boFail                                : Boolean;
begin
  if m_boPneuma then Exit;
  if m_boGhost or m_boDeath then Exit;
  if nCJIdx = 0 then Exit;
  if (nCount = 0) or (nCount > 8) then Exit;
  if (sData = '') then Exit;

  if GetXmlAchievement(nCJIdx) = nil then Exit;

  FillChar(nMakeIndexs, SizeOf(DWORD) * 8, 0);
  DeCodeBuffer(sData, @nMakeIndexs[0], SizeOf(Integer) * nCount);
  boFail := False;

  if GetAchievementInfo(nCJIdx) = nil then begin
    for i := 0 to nCount - 1 do begin
      if GetUserItemByMakeIndex(nMakeIndexs[i], UserItem) = -1 then begin
        boFail := True;
        Break;
      end;
    end;
  end else begin
    boFail := True;
  end;

  if not boFail then begin
    m_sScriptParam[0] := IntToStr(nCount);
    for i := 0 to 7 do
      m_sScriptParam[i + 1] := IntToStr(nMakeIndexs[i]);
    ExecuteScript(g_FunctionNPC, '@套装成就' + IntToStr(nCJIdx));

    //如果物品还存在,也是失败
    if GetUserItemByMakeIndex(nMakeIndexs[0], UserItem) <> -1 then begin
      boFail := True;
    end;
  end;
  SendDefMessage(SM_ACHIEVEMENT__OK, Integer(Self), 1, Integer(boFail), 0, '');
end;

procedure TPlayObject.SendPetAttribute(PlayObject: TPlayObject; btWhere: byte; UserItem: pTUserItem); //发送灵兽石附加属性
begin
  if Assigned(m_VersionManage) then
  try
    m_VersionManage.OnSendPetAttribute(Self, PlayObject, btWhere, UserItem);
  except
    MainOutMessage(Format('TPlayObject::OnSendPetAttribute SoftVersionDate:%d', [m_VersionManage.SoftVersionDate]));
  end;
end;

procedure TPlayObject.SendBagItemsPetInfo();
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
  i, n15, n16                           : Integer;
  RidePetInfo                           : TRidePetInfo;
  SoulPetInfoAdd                        : TSoulPetInfoAdd;
  SoulPetInfo                           : TSoulPetInfo;
begin
  n15 := 0;
  n16 := 0;
  g_SmallPacketManage.Init;
  g_PacketManage3.Init;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := m_ItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem <> nil then begin
      if (StdItem.StdMode = 49) and (StdItem.Shape = 51) then begin
        RidePetInfo := UserItem.GetRidePetInfo;
        RidePetInfo.btRace := MakeByte(UserItem.btValue[8], StdItem.AniCount);

        //3转灵兽
        if (UserItem.btValue[9] > 2) then begin
          SoulPetInfoAdd := UserItem.GetSoulPetInfoAdd;
          SoulPetInfoAdd.btRace := RidePetInfo.btRace;
          SoulPetInfo := UserItem.GetSoulPetInfo;
          //写入三转灵兽属性
          g_PacketManage3.WriteBuffer(SoulPetInfoAdd, SizeOf(TSoulPetInfoAdd));
          //在写一遍魂佑信息
          g_PacketManage3.WriteBuffer(SoulPetInfo, SizeOf(TSoulPetInfo));
          //技能信息,填0就可以了
          g_PacketManage3.FillWrite(64, 0);
          Inc(n15);
        end else begin
          g_SmallPacketManage.WriteBuffer(RidePetInfo, SizeOf(TRidePetInfo));
          Inc(n16);
        end;
      end;
    end;
  end;

  for i := 0 to m_PetItemList.Count - 1 do begin
    UserItem := m_PetItemList.Items[i];
    StdItem := UserEngine.GetStdItem(UserItem.wIndex);
    if StdItem <> nil then begin
      if (StdItem.StdMode = 49) and (StdItem.Shape = 51) then begin
        RidePetInfo := UserItem.GetRidePetInfo;
        RidePetInfo.btRace := MakeByte(UserItem.btValue[8], StdItem.AniCount);

        //3转灵兽
        if (UserItem.btValue[9] > 2) then begin
          SoulPetInfoAdd := UserItem.GetSoulPetInfoAdd;
          SoulPetInfoAdd.btRace := RidePetInfo.btRace;
          SoulPetInfo := UserItem.GetSoulPetInfo;
          //写入三转灵兽属性
          g_PacketManage3.WriteBuffer(SoulPetInfoAdd, SizeOf(TSoulPetInfoAdd));
          //在写一遍魂佑信息
          g_PacketManage3.WriteBuffer(SoulPetInfo, SizeOf(TSoulPetInfo));
          //技能信息,填0就可以了
          g_PacketManage3.FillWrite(64, 0);
          Inc(n15);
        end else begin
          g_SmallPacketManage.WriteBuffer(RidePetInfo, SizeOf(TRidePetInfo));
          Inc(n16);
        end;
      end;
    end;

  end;

  if (n16 > 0) or (n15 > 0) then begin
    g_SmallPacketManage.WriteInteger($007A2626);
    g_SmallPacketManage.WriteWord(n15);                                                             //数量
    g_SmallPacketManage.WriteBuffer(g_PacketManage3.Memory^, g_PacketManage3.Position);

    m_defMsg := MakeDefaultMsg(SM_RIDEPETINFO, Integer(Self), 24, 0, n16);
    SendSocket(@m_defMsg, g_SmallPacketManage.GetMsg());
  end;
end;

function TPlayObject.TrainingPetSkill(const StdItem: pTStdItem): Boolean;
var
  i, btPos                              : Integer;
  btID, btLv                            : byte;
  UserItem                              : pTUserItem;
  //  StdItemA                         : pTStdItem;
  boFound                               : Boolean;
begin
  Result := False;
  boFound := False;
  if (m_Pet <> nil) then begin
    for i := 0 to m_ItemList.Count - 1 do begin
      UserItem := m_ItemList[i];
      if UserItem.MakeIndex = m_PetInfo[0].nMakeIndex then begin
        boFound := True;
        Break;
      end;
    end;
  end;

  if (not boFound) or (UserItem.btItemExt[29] < 2) then begin
    SysMsg('请放出一只魂佑灵兽并使之处于跟随状态', c_Red, t_Hint);
    Exit;
  end;

  if (UserItem.wLevel < StdItem.NeedLevel) then begin
    SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '灵兽等级不够');
    Exit;
  end;

  //  $PETMAGIC(X)
  btPos := -1;
  for i := 9 downto 0 do begin
    btID := UserItem.btExtra.PetMagics[i].GetID();
    btLv := UserItem.btExtra.PetMagics[i].GetLv();
    if (btLv > 0) then begin
      if (btID = LoWord(StdItem.AC)) then begin
        btPos := -2;
        Break;
      end;
    end else
      btPos := i;
  end;

  case btPos of
    -1: begin
        SysMsg('已经没有技能空位来学习新技能了,请清空技能格后再来学习', c_Red, t_Hint);
        Exit;
      end;
    -2: begin
        SendMsg(g_ManageNPC, RM_MENU_OK, 0, Integer(Self), 0, 0, '该灵兽已经习得这个技能。');
        Exit;
      end;
  else begin
      Result := True;
      btID := LoWord(StdItem.AC);
      btLv := StdItem.DuraMax + 1;
      if (btPos in [0..9]) and (btLv in [1..4]) then begin
        UserItem.btExtra.PetMagics[btPos].SetInfo(btID, btLv);
        m_defMsg := MakeDefaultMsg(SM_COMPREHENDSKILL, Integer(Self), LoWord(UserItem.MakeIndex), HiWord(UserItem.MakeIndex), MakeWord(btLv, btID));
        SendSocket(@m_defMsg, EnCodeBuffer(@btPos, 1));
      end;
    end;
  end;
end;

procedure TPlayObject.SendStruckMsg(wIdent: word; BaseObject, Attacker: TBaseObject; nDamage: Integer; wEffect: word);
begin
  if g_Config.boDisableSelfStruck and (BaseObject = Self) then Exit;

  g_SmallPacketManage.Init;

  //发送心魔、人类 攻击值
{$IF DEMONSERVER = 1}
  if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) and (m_btDemonMode > 0) then begin
    g_PacketManage3.Init;
    g_PacketManage3.WriteByte(1);
    g_PacketManage3.WriteByte(m_btDemonForce);
    g_PacketManage3.WriteInteger(Integer(Self));
    g_PacketManage3.WriteInteger(0);
    SendRefMsg(RM_DEMONHIT, 0, Integer(Self), 0, 0, g_PacketManage3.GetMsg);
    if (m_btDemonForce = 0) then begin
      m_sScriptParam[0] := IntToStr(m_btDemonMode);
      m_btDemonMode := 0;
      ExecuteScript(g_FunctionNPC, '@_心魔_人类心魔被杀');
    end;
  end;
{$IFEND}
  if (BaseObject <> nil) and (not BaseObject.m_boDeath) then begin
    g_SmallPacketManage.WriteInteger(BaseObject.GetFeature(nil));
    g_SmallPacketManage.WriteInteger(BaseObject.m_nCharStatus);
    g_SmallPacketManage.WriteInteger(Integer(Attacker));
    //人被攻击
    if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) then begin
      if wIdent = RM_STRUCK_NEWMAG1 then begin
        g_SmallPacketManage.WriteInteger(MakeLong(0, wEffect));
        if (BaseObject = Self) then begin
          m_defMsg := MakeDefaultMsg(SM_47,
            Integer(BaseObject),
            BaseObject.m_WAbil.dwHP,
            BaseObject.m_WAbil.dwMaxHP,
            nDamage);

          g_SmallPacketManage.WriteWord(BaseObject.m_WAbil.wElementForce);                          //自己被攻击才会发送元力的信息
          g_SmallPacketManage.WriteWord(BaseObject.m_WAbil.wElementForceMax);
          g_SmallPacketManage.WriteByte(02);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwHP);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwMaxHP);
        end else begin
          m_defMsg := MakeDefaultMsg(SM_47,
            Integer(BaseObject),
            CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP),
            CalcCent(BaseObject.m_WAbil.wElementForce, BaseObject.m_WAbil.wElementForceMax),
            nDamage);

          g_SmallPacketManage.WriteByte(02);
          g_SmallPacketManage.WriteInteger(0);
          g_SmallPacketManage.WriteInteger(0);
        end;
      end else begin
        //人被攻击 会带有时间参数
        g_SmallPacketManage.WriteInteger(DateTimeToWolTIme(Now));
        if (BaseObject = Self) then begin
          m_defMsg := MakeDefaultMsg(SM_STRUCK,
            Integer(BaseObject),                                                                    //被攻击者
            BaseObject.m_WAbil.dwHP,
            BaseObject.m_WAbil.dwMaxHP,
            nDamage);

          g_SmallPacketManage.WriteWord(BaseObject.m_WAbil.wElementForce);                          //自己被攻击才会发送元力的信息
          g_SmallPacketManage.WriteWord(BaseObject.m_WAbil.wElementForceMax);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwHP);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwMaxHP);
        end else begin
          m_defMsg := MakeDefaultMsg(SM_STRUCK,
            Integer(BaseObject),                                                                    //被攻击者
            CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP),
            CalcCent(BaseObject.m_WAbil.wElementForce, BaseObject.m_WAbil.wElementForceMax),
            nDamage);

          g_SmallPacketManage.WriteInteger(0);
          g_SmallPacketManage.WriteInteger(0);
        end;
      end;
    end else begin
      if wIdent = RM_STRUCK_NEWMAG1 then begin
        m_defMsg := MakeDefaultMsg(SM_47,
          Integer(BaseObject),
          CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP),
          BaseObject.m_wMaxHPCent,
          nDamage);

        g_SmallPacketManage.WriteInteger(MakeLong(0, wEffect));
        g_SmallPacketManage.WriteInteger(0);
        g_SmallPacketManage.WriteByte(0);
        if BaseObject.m_WAbil.dwMaxHP > High(word) then begin
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwHP);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwMaxHP);
        end else begin
          g_SmallPacketManage.WriteInteger(CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP));
          g_SmallPacketManage.WriteInteger($64);
        end;
      end else begin
        m_defMsg := MakeDefaultMsg(SM_STRUCK,
          Integer(BaseObject),                                                                      //被攻击者
          CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP),
          BaseObject.m_wMaxHPCent,
          nDamage);
        g_SmallPacketManage.WriteInteger(0);
        if BaseObject.m_WAbil.dwMaxHP > High(word) then begin
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwHP);
          g_SmallPacketManage.WriteInteger(BaseObject.m_WAbil.dwMaxHP);
        end else begin
          g_SmallPacketManage.WriteInteger(CalcCent(BaseObject.m_WAbil.dwHP, BaseObject.m_WAbil.dwMaxHP));
          g_SmallPacketManage.WriteInteger($64);
        end;
      end;
    end;

    g_SmallPacketManage.WriteInteger(0);
    g_SmallPacketManage.WriteInteger(0);
    SendSocket(@m_defMsg, g_SmallPacketManage.GetMsg);
  end;
end;

procedure TPlayObject.OnEnvirnomentChanged(OldEnvir: TEnvirnoment; boChanged: Boolean = True);
begin
  inherited OnEnvirnomentChanged(OldEnvir, boChanged);
  if boChanged then begin
    if (m_Pet <> nil) and (m_PetInfo[0].btType in [26..28]) and (not m_PEnvir.m_MapFlag.boCanRideShark) then begin //鲨鱼在普通地图不能出现
      PetHide(m_PetInfo[0].nMakeIndex);
    end;

    if (m_Tiger <> nil) and m_PEnvir.m_MapFlag.boNOTIGER then begin
      ClientReCallTiger;
    end;

    //心魔控制面板
    if (m_nEvilFollowerPower > 0) then begin
      ClientQueryEvilFollower;
    end;

    m_sTimerLabel := '';
    m_dwTimerLong := 0;
    m_sMapNewDesc := '';

    if (OldEnvir <> nil) then
      m_sScriptParam[0] := OldEnvir.m_sMapName
    else
      m_sScriptParam[0] := '';

    ExecuteScript(g_FunctionNPC, '@地图变更');
  end;
end;

//升级灵兽装备

procedure TPlayObject.ClientPetEquipUp(nPetItemIdx, nStoreItemIdx: Integer; sData: string);
var
  nGemItemIdx                           : array[0..1] of Integer;
begin
  if (nPetItemIdx = 0) or (nStoreItemIdx = 0) then Exit;
  if (sData = '') then Exit;
  FillChar(nGemItemIdx, SizeOf(Integer) * 2, 0);
  DeCodeBuffer(sData, @nGemItemIdx[0], SizeOf(Integer) * 2);

  m_sScriptParam[0] := IntToStr(nPetItemIdx);
  m_sScriptParam[1] := IntToStr(nStoreItemIdx);
  m_sScriptParam[2] := IntToStr(nGemItemIdx[0]);
  m_sScriptParam[3] := IntToStr(nGemItemIdx[1]);

  if m_ClickNPC <> nil then
    TNormNpc(m_ClickNPC).GotoLable(Self, '@@PetEquipUp', False);
end;

procedure TPlayObject.SlaveTransferDamage(var nDamage: Integer);
var
  i, nTransfer, nObjCount               : Integer;
  BaseObject                            : TBaseObject;
begin
  for i := 0 to m_SlaveList.Count - 1 do begin
    BaseObject := m_SlaveList[i];
    if BaseObject.m_boIsGodCallBoss or BaseObject.m_boScapeGoat or BaseObject.m_boIsPet or
      BaseObject.m_boGodCallBoss or (BaseObject.m_btRaceServer in [212, 214]) or (BaseObject.m_boStickMode) or
      (BaseObject.m_btRaceServer in [206]) then
      Continue;

    if CretInNear10XY(BaseObject, m_nCurrX, m_nCurrY) then begin
      nObjCount := Integer(Self);
      BaseObject.SendRefMsg(RM_510, HiWord(nObjCount), LoWord(nObjCount), 104, 0, '');
      nTransfer := Round(nDamage * (_MIN(m_WAbil.btShiftDamage, 90)) / 100);
      Dec(nDamage, nTransfer);
      if nTransfer > 0 then begin
        BaseObject.StruckDamage(nTransfer);
        BaseObject.SendRefMsg(RM_STRUCK, 0, nTransfer, 0, Integer(Self), '');
      end;
    end;
    Break;
  end;
end;

procedure TPlayObject.BaoBaoTransferDamage(var nDamage: Integer);                                   //道神符印斗转
var
  i, nTransfer, nObjCount               : Integer;
  BaseObject                            : TBaseObject;
begin
  for i := 0 to m_SlaveList.Count - 1 do begin
    BaseObject := m_SlaveList[i];
    if (not BaseObject.m_boProBaoBao) then
      Continue;
    if CretInNear10XY(BaseObject, m_nCurrX, m_nCurrY) then begin
      nObjCount := Integer(Self);
      BaseObject.SendRefMsg(RM_510, HiWord(nObjCount), LoWord(nObjCount), 104, 0, '');
      nTransfer := Round(nDamage * (_MIN(g_Config.nDouZhuanDamagePercent, 90)) / 100);
      Dec(nDamage, nTransfer);
      if nTransfer > 0 then begin
        BaseObject.StruckDamage(nTransfer);
        BaseObject.SendRefMsg(RM_STRUCK, 0, nTransfer, 0, Integer(Self), '');
      end;
    end;
    Break;
  end;
end;

//化身蝙蝠、遁地、移行换影

function TPlayObject.MagDoBatfly(UserMagic: pTUserMagic; nTargetX, nTargetY: Integer): Boolean;
var
  FlyData                               : TShunyiData;
  s1C, sName                            : string;
  nPower, nMagID, nSecPwr, n20          : Integer;
  nOldX, nOldY                          : Integer;
  i, nDir, nX, nY, nRage                : Integer;
  nFireTime                             : Integer;
  nBatflyRate, nBatflyMaxRage           : Integer;
  Event                                 : TEvent;
  BaseObjectList                        : TList;
  BaseObject                            : TBaseObject;
  bo18, boCanHit                        : Boolean;
begin
  Result := False;
  bo18 := False;
  boCanHit := m_PEnvir.CanWalk(nTargetX, nTargetY, False);
//  if (GetTickCount - UserMagic.nTranPoint) < UserMagic.MagicInfo.dwCoolDownTime then begin
//    SysMsg(format('无法连续使用该技能,请%d秒后再使用。', [(UserMagic.MagicInfo.dwCoolDownTime - (GetTickCount - UserMagic.nTranPoint)) div 1000]), c_Red, t_Hint);
//    Exit;
//  end;
//  UserMagic.nTranPoint := GetTickCount;              //保存技能的使用时间
  if not boCanHit then begin
    //先获取首要方向
    nDir := GetNextDirection(nTargetX, nTargetY, m_nCurrX, m_nCurrY);
    while True do begin
      if m_PEnvir.GetNextPosition(nTargetX, nTargetY, nDir, 1, nX, nY) then begin
        boCanHit := m_PEnvir.CanWalk(nX, nY, False);
      end;
      if boCanHit or (nDir >= 7) then Break;

      //如果没有找到位置,就换个方向
      if not bo18 then begin
        nDir := 0;
        bo18 := True;
      end else
        Inc(nDir);
    end;
  end else begin
    nX := nTargetX;
    nY := nTargetY;
  end;

  //技能参数
  if g_Config.boUseXMLMagicSkill then begin
    nBatflyRate := g_MagicSkill[UserMagic.GetMagIdx].btLv[UserMagic.btLevel].btVal[2];
    nBatflyMaxRage := g_MagicSkill[UserMagic.GetMagIdx].btLv[UserMagic.btLevel].btVal[1];
  end else begin
    nBatflyRate := UserMagic.btLevel + 1;
    nBatflyMaxRage := g_Config.nBatflyMaxRage;
  end;

  if (m_wStatusTimeArr[STATE_FREEZE {冰冻}] <> 0) then begin
    SysMsg('被冰冻无法使用瞬移技能。', c_Red, t_Hint);
  end else if m_PEnvir.m_MapFlag.boNoBatfly then begin
    SysMsg('此地图禁止使用瞬移技能。', c_Red, t_Hint);
  end else if m_boArrow then begin
    SysMsg('你正在执行抢宝任务,禁止使用瞬移技能。', c_Red, t_Hint);
  end else if (not boCanHit) or
    (abs(nTargetX - m_nCurrX) > nBatflyMaxRage) or (abs(nTargetY - m_nCurrY) > nBatflyMaxRage) then begin
    SysMsg('此点不能到达', c_Red, t_Hint);
  end else if InWarSnareZone(m_PEnvir, m_nCurrX, m_nCurrY) and (not g_EventManager.InWarSnareZone(m_PEnvir, nTargetX, nTargetY)) then begin
    SysMsg('你已被战争牢笼困住,无法逃脱!', c_Red, t_Hint);
  end else begin
    //检测下附近有没有人在使用战争旋风
    if not g_Config.boAntiWarWhirlWind then begin
      BaseObjectList := TList.Create;
      try
        GetMapBaseObjects(m_PEnvir, m_nCurrX, m_nCurrY, 3, BaseObjectList);
        for i := 0 to BaseObjectList.Count - 1 do begin
          BaseObject := TBaseObject(BaseObjectList.Items[i]);
          if (BaseObject.m_btRaceServer <> RC_PLAYOBJECT) then Continue;
          if (BaseObject.m_wStatusTimeArr[STATE_WARWHIRLWIND] > 0) and (BaseObject.IsProperTarget(Self)) then begin
            SysMsg('因为中了战争旋风,此技能被限制', c_Red, t_Hint);
            Exit;
          end;
        end;
      finally
        BaseObjectList.free;
      end;
    end;

    if (Random(g_Config.nBatflyRate) < nBatflyRate) and
      (m_PEnvir.DeleteFromMap(m_nCurrX, m_nCurrY, OS_MOVINGOBJECT, Self) > 0) then begin
      m_btDirection := GetNextDirection(m_nCurrX, m_nCurrY, nX, nY);
      nOldX := m_nCurrX;
      nOldY := m_nCurrY;
      m_nCurrX := nX;
      m_nCurrY := nY;
      m_PEnvir.AddToMap(m_nCurrX, m_nCurrY, OS_MOVINGOBJECT, Self);
      RunStepToDamage(_Max(abs(nOldX - m_nCurrX), abs(nOldY - m_nCurrY)));
      Result := True;
    end;

    if Result then begin
      FlyData.CharDesc.Feature := GetFeatureToLong(Self);
      FlyData.CharDesc.Status := m_nCharStatus;
      FlyData.CharDesc.Featurex := GetMaxHPCent(Self);
      FlyData.nX := nOldX;
      FlyData.nY := nOldY;
      FlyData.wKnow := $01FF;
      FlyData.MagCode := UserMagic.GetMagIdx;
      sName := GetShowName;
      g_SmallPacketManage.Init;
      g_SmallPacketManage.WriteBuffer(FlyData, SizeOf(TShunyiData));
      g_SmallPacketManage.WriteBuffer(sName[1], Length(sName));
      g_SmallPacketManage.FillWrite(27, 0);
      s1C := g_SmallPacketManage.GetMsg;
      n20 := 0;
      if UserMagic.btLevel > 3 then n20 := $0A;
      SendRefMsg(RM_170, MakeWord(m_btDirection, n20 or m_btGender), m_nCurrX, m_nCurrY, 0, s1C);

      if (m_btRaceServer = RC_PLAYOBJECT) and m_boRideFightOn then begin
        case UserMagic.GetMagIdx of
          SKILL_WINDTEBO: begin
              //火蝙蝠
              if (m_MagicSkills[SKILL_BATFIRE] <> nil) and (m_MagicSkills[SKILL_BATFIRE].btKey = 1) and (m_MagicSkills[SKILL_FIRE] <> nil) then begin
                n20 := m_PetInfo[2].wLevel + m_MagicSkills[SKILL_BATFIRE].btLevel + m_MagicSkills[SKILL_FIRE].btLevel + UserMagic.btLevel;
                if (Random(g_Config.nMagBatFireRate) < n20) then begin
                  //获得火蝙蝠的威力
                  nPower := GetAttackPower(GetPower(MPow(m_MagicSkills[SKILL_BATFIRE]), m_MagicSkills[SKILL_BATFIRE]) + loword(m_WAbil.MC), SmallInt(hiword(m_WAbil.MC) - loword(m_WAbil.MC)) + 1, SKILL_BATFIRE);
                  nSecPwr := Trunc(nPower * n20 / 500);
                  Inc(nPower, nSecPwr);
                  //控制时间
                  nFireTime := GetPower(10, UserMagic) + (word(GetRPow(m_WAbil.MC)) shr 1);
                  if g_Config.boUseFireDelayTime and (g_Config.nFireDelayTime > 0) then nFireTime := _MIN(nFireTime, g_Config.nFireDelayTime);
                  //最长距离
                  nRage := _Max(abs(nOldX - m_nCurrX), abs(nOldY - m_nCurrY));
                  //从原始坐标到目标坐标
                  nDir := GetNextDirection(nOldX, nOldY, m_nCurrX, m_nCurrY);
                  nX := nOldX;
                  nY := nOldY;
                  for i := 1 to nRage do begin
                    Event := TEvent(m_PEnvir.GetEvent(nX, nY));
                    //清除火墙和流星火雨
                    if (Event <> nil) and (Event.m_nEventType in [ET_FIRERAIN, ET_GODFIRERAIN, ET_EVILFIRERAIN]) then begin
                      Event.m_boClosed := True;
                      Event.Close;
                      Event := nil;
                    end;

                    if Event = nil then begin
                      SendDelayMsg(Self, RM_DELAYFIREBURN, ET_BATFIRE, MakeLong(nX, nY), nFireTime * 1000, nPower, '', 100);
                    end;

                    if not ((abs(nX - m_nCurrX) <= 0) and (abs(nY - m_nCurrY) <= 0)) then begin
                      nDir := GetNextDirection(nX, nY, m_nCurrX, m_nCurrY);
                      if not m_PEnvir.GetNextPosition(nX, nY, nDir, 1, nX, nY) then
                        Break;
                    end else
                      Break;
                  end;
                end;
              end;
            end;
          SKILL_75: ;
          SKILL_77: begin
              if (m_MagicSkills[SKILL_BANWOL] <> nil) then nMagID := SKILL_BANWOL else nMagID := SKILL_43;

              if (m_MagicSkills[SKILL_SHADOWKILL] <> nil) and (m_MagicSkills[SKILL_SHADOWKILL].btKey = 1) and (m_MagicSkills[nMagID] <> nil) then begin
                //影袭杀
                n20 := m_PetInfo[2].wLevel + m_MagicSkills[SKILL_SHADOWKILL].btLevel + m_MagicSkills[nMagID].btLevel + UserMagic.btLevel;
                if (Random(g_Config.nMagShadowKillRate) < n20) then begin
                  SendAttackMsg(RM_WIDEHIT, $1800 or m_btDirection, m_nCurrX, m_nCurrY);
                  nPower := GetAttackPower(GetPower(MPow(UserMagic), UserMagic) + loword(m_WAbil.DC), SmallInt(hiword(m_WAbil.DC) - loword(m_WAbil.DC)) + 1, SKILL_SHADOWKILL);
                  nSecPwr := Trunc(nPower * n20 / 500);
                  Inc(nPower, nSecPwr);
                  MagicManager.MagBigExplosion(Self, nPower, m_nCurrX, m_nCurrY, 1);
                end;
              end;
            end;
        end;
      end;
    end else begin
      case UserMagic.GetMagIdx of
        SKILL_WINDTEBO: SysMsg('化身蝙蝠失败', c_Red, t_Hint);
        SKILL_75: SysMsg('使用遁地失败', c_Red, t_Hint);
        SKILL_77: SysMsg('移形换影失败', c_Red, t_Hint);

      end;
      Result := False;
    end;
  end;
end;

function TPlayObject.CheckEatItems(StdItem: pTStdItem): Boolean;
var
  n, i                                  : Integer;
begin
  Result := False;
  n := 0;
  i := 0;
  case StdItem.Need of
    0: Result := True;
    1: begin;                                                                                       //需要等级
        if (StdItem.NeedLevel > 71) then begin
          n := Ceil((StdItem.NeedLevel - 71) / 99);
          i := (StdItem.NeedLevel - 71) - 99 * (n - 1);

          if ((Ceil(m_btAmbitKind / 2) - 1) > n) or (((Ceil(m_btAmbitKind / 2) - 1) = n) and (m_btAmbitLevel >= i)) then begin
            Result := True;
          end;
        end else begin
          if m_Abil.level >= StdItem.NeedLevel then begin
            Result := True;
          end;
        end;
      end;
    2: begin;                                                                                       //需要勋爵等级
        if m_wCentsOfficerLevel > StdItem.NeedLevel then begin
          Result := True;
        end;
      end;
  end;
end;

procedure TPlayObject.ClientPerfectStoreMoveHome(nParam1: Integer; nMapIdx: Integer);
const
  mapName                               : array[0..7] of string = ('0', '1', '4', '7', '2', '5', 'haidi', 'zqd');
  HomeX                                 : array[0..7] of Integer = (474, 229, 350, 54, 223, 462, 157, 156);
  HomeY                                 : array[0..7] of Integer = (222, 241, 165, 41, 448, 107, 182, 118);
  mapName1                              : array[0..6] of string = ('0', '0', '4', '7', '2', '5', '1');
  HomeX1                                : array[0..6] of Integer = (474, 0, 350, 54, 223, 462, 229);
  HomeY1                                : array[0..6] of Integer = (222, 0, 165, 41, 448, 107, 241);
var
  i, j                                  : Integer;
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  if (m_wShopItemCount > 0) or m_boArrow then Exit;                                                 //禁止使用回城石的条件
  if (GetTickCount - m_dwUseStoreTick) < 10000 then begin
    SysMsg('每隔10秒才允许使用回城石一次。', c_Red, t_Hint);
    Exit;
  end;

  if m_PEnvir.m_MapFlag.boNOSTOREMOVE then begin
    SysMsg('当前地图禁止使用回城石。', c_Red, t_Hint);
    Exit;
  end;

  if (nMapIdx < 0) or (nMapIdx > 7) then Exit;
  for i := 0 to m_ItemList.Count - 1 do begin
    UserItem := pTUserItem(m_ItemList[i]);
    if UserItem.MakeIndex = nParam1 then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if (StdItem.StdMode = 3) and ((StdItem.Shape = 15) or (StdItem.Shape = 17)) then begin
        if not (g_Config.boClassicServer) then begin
          m_sScriptParam[0] := m_PEnvir.m_sMapName;
          m_sScriptParam[1] := mapName1[nMapIdx];
          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
          SpaceMove(mapName1[nMapIdx], HomeX1[nMapIdx] + Random(8) - 4, HomeY1[nMapIdx] + Random(8) - 4, 0, nil);
        end else begin
          m_sScriptParam[0] := m_PEnvir.m_sMapName;
          m_sScriptParam[1] := mapName[nMapIdx];
          SendRefMsg(RM_SPACEMOVE_FIRE, 0, 0, 0, 0, '');
          SpaceMove(mapName[nMapIdx], HomeX[nMapIdx] + Random(8) - 4, HomeY[nMapIdx] + Random(8) - 4, 0, nil);
        end;
        m_dwUseStoreTick := GetTickCount;
        SendRefMsg(RM_510, 1, 0, 29, 0, '');
        ExecuteScript(g_FunctionNPC, '@使用回城石');
        if (StdItem.Shape = 17) then begin
          if UserItem.Dura > 0 then Dec(UserItem.Dura);
          if (UserItem.Dura <= 0) then begin
            SendDelItems(UserItem);
            DelBagItem(UserItem.MakeIndex, '');
          end else begin
            SendDefMessage(SM_EAT_FAIL, 0, 0, 0, 0, '');
            SendUpdateItem(UserItem);
          end;
        end;
      end;
      Break;
    end;
  end;

end;

procedure TPlayObject.KillMonsterFunc();
begin
  if (m_PEnvir.m_MapFlag.sMapFuncLabel <> '') then begin
    ExecuteScript(g_ManageNPC, m_PEnvir.m_MapFlag.sMapFuncLabel);
  end;
  ExecuteScript(g_FunctionNPC, '@杀怪触发');
end;

procedure TPlayObject.KillPlayerFunc();
begin
  if (m_LastHiter <> nil) and (m_LastHiter.m_btRaceServer = RC_PLAYOBJECT) then begin
    TPlayObject(m_LastHiter).m_sScriptParam[0] := m_sCharName;
    TPlayObject(m_LastHiter).m_sScriptParam[1] := m_PEnvir.m_sMapName;
    TPlayObject(m_LastHiter).m_sScriptParam[2] := IntToStr(m_nCurrX);
    TPlayObject(m_LastHiter).m_sScriptParam[3] := IntToStr(m_nCurrY);
    TPlayObject(m_LastHiter).m_sScriptParam[4] := m_PEnvir.m_sMapDesc;
    TPlayObject(m_LastHiter).m_sScriptParam[5] := IntToStr(m_btCountry);

    (m_LastHiter as TPlayObject).ExecuteScript(g_FunctionNPC, '@谋杀他人');
    //被人谋杀执行脚本
    TPlayObject(Self).m_sScriptParam[0] := m_LastHiter.m_sCharName;
    TPlayObject(Self).m_sScriptParam[1] := m_LastHiter.m_PEnvir.m_sMapName;
    TPlayObject(Self).m_sScriptParam[2] := IntToStr(m_LastHiter.m_nCurrX);
    TPlayObject(Self).m_sScriptParam[3] := IntToStr(m_LastHiter.m_nCurrY);
    TPlayObject(Self).m_sScriptParam[4] := m_LastHiter.m_PEnvir.m_sMapDesc;
    TPlayObject(Self).m_sScriptParam[5] := IntToStr(m_LastHiter.m_btCountry);
    ExecuteScript(g_FunctionNPC, '@被人谋杀');
  end;
end;

procedure TPlayObject.RecalcAddProvisionalAbil;
var
  i                                     : Integer;
begin
  for i := Low(TProvisionalAbil) to High(TProvisionalAbil) do begin
    case i of
      0: m_AddAbil.wAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wAC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.wAC)); //AC1          //防御
      1: m_AddAbil.wAC := MakeLong(loword(m_AddAbil.wAC), _MIN(High(MaxInt), hiword(m_AddAbil.wAC) + m_ProvisionalAbil[i])); //AC2          //防御
      2: m_AddAbil.wMAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMAC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.wMAC)); //MAC1         //魔法防御
      3: m_AddAbil.wMAC := MakeLong(loword(m_AddAbil.wMAC), _MIN(High(MaxInt), hiword(m_AddAbil.wMAC) + m_ProvisionalAbil[i])); //MAC2         //魔法防御
      4: m_AddAbil.wDC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wDC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.wDC)); //DC1          //攻击
      5: m_AddAbil.wDC := MakeLong(loword(m_AddAbil.wDC), _MIN(High(MaxInt), hiword(m_AddAbil.wDC) + m_ProvisionalAbil[i])); //DC2          //攻击
      6: m_AddAbil.wMC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.wMC)); //MC1          //魔法
      7: m_AddAbil.wMC := MakeLong(loword(m_AddAbil.wMC), _MIN(High(MaxInt), hiword(m_AddAbil.wMC) + m_ProvisionalAbil[i])); //MC2          //魔法
      8: m_AddAbil.wSC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wSC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.wSC)); //SC1          //道术
      9: m_AddAbil.wSC := MakeLong(loword(m_AddAbil.wSC), _MIN(High(MaxInt), hiword(m_AddAbil.wSC) + m_ProvisionalAbil[i])); //SC2          //道术
      10: m_AddAbil.dwHP := _MIN(MAXHUMHP, m_AddAbil.dwHP + m_ProvisionalAbil[i]);                  //HP           //生命值
      11: m_AddAbil.dwMP := _MIN(MAXHUMMP, m_AddAbil.dwMP + m_ProvisionalAbil[i]);                  //MP           //魔法值
      12: m_AddAbil.btLuck := _MIN(High(byte), m_AddAbil.btLuck + m_ProvisionalAbil[i]);            //Luck         //幸运
      13: m_AddAbil.btUnLuck := _MIN(High(byte), m_AddAbil.btUnLuck + m_ProvisionalAbil[i]);        //UnLuck       //诅咒
      14: m_AddAbil.wSpeedPoint := _MIN(High(MaxInt), m_AddAbil.wSpeedPoint + m_ProvisionalAbil[i]); //SPEED        //躲避
      15: m_AddAbil.wAntiMagic := _MIN(High(MaxInt), m_AddAbil.wAntiMagic + m_ProvisionalAbil[i]);  //AntiMagic    //魔法躲避
      16: m_AddAbil.wAntiPoison := _MIN(High(MaxInt), m_AddAbil.wAntiPoison + m_ProvisionalAbil[i]); //AntiPoison   //中毒躲避
      17: m_AddAbil.wHitPoint := _MIN(High(MaxInt), m_AddAbil.wHitPoint + m_ProvisionalAbil[i]);    //HIT          //命中
      18: m_AddAbil.btMagicNicety := _MIN(High(MaxInt), m_AddAbil.btMagicNicety + m_ProvisionalAbil[i]); //MagicNicety  //魔法命中
      19: m_AddAbil.btPoisonNicety := _MIN(High(MaxInt), m_AddAbil.btPoisonNicety + m_ProvisionalAbil[i]); //PoisonNicety //中毒命中
      20: Inc(m_nHongMoSuite, m_ProvisionalAbil[i]);
      21: m_AddAbil.btShiftDamage := _MIN(High(byte), m_AddAbil.btShiftDamage + m_ProvisionalAbil[i]); //ShiftDamage,  /伤害转移
      22: m_AddAbil.btReflexDamage := _MIN(High(byte), m_AddAbil.btReflexDamage + m_ProvisionalAbil[i]); //ReflexDamage, /伤害反射
      23: m_AddAbil.wPetFelementPoint[0] := _MIN(High(Word), m_AddAbil.wPetFelementPoint[0] + m_ProvisionalAbil[i]); //Gold  金属性
      24: m_AddAbil.wPetFelementPoint[1] := _MIN(High(Word), m_AddAbil.wPetFelementPoint[1] + m_ProvisionalAbil[i]); //Wood  木属性
      25: m_AddAbil.wPetFelementPoint[2] := _MIN(High(Word), m_AddAbil.wPetFelementPoint[2] + m_ProvisionalAbil[i]); //Soil  水属性
      26: m_AddAbil.wPetFelementPoint[3] := _MIN(High(Word), m_AddAbil.wPetFelementPoint[3] + m_ProvisionalAbil[i]); //Water 火属性
      27: m_AddAbil.wPetFelementPoint[4] := _MIN(High(Word), m_AddAbil.wPetFelementPoint[4] + m_ProvisionalAbil[i]); //Fire  土属性
      28: m_AddAbil.btThump := _MIN(High(Word), m_AddAbil.btThump + m_ProvisionalAbil[i]);          //Thump 爆击机率
      29: m_AddAbil.btReduceAC := _MIN(High(Byte), m_AddAbil.btReduceAC + m_ProvisionalAbil[i]);    //ReduceAC,         /减免对方物理防御
      30: m_AddAbil.btReduceMAC := _MIN(High(Byte), m_AddAbil.btReduceMAC + m_ProvisionalAbil[i]);  //ReduceMAC,        /减免对方魔法防御
      31: m_AddAbil.btReduceSpeedPoint := _MIN(High(Byte), m_AddAbil.btReduceSpeedPoint + m_ProvisionalAbil[i]); //ReduceSpeedPoint, /减免对方物理躲避
      32: m_AddAbil.btReduceAntiMagic := _MIN(High(Byte), m_AddAbil.btReduceAntiMagic + m_ProvisionalAbil[i]); //ReduceAntiMagic,  /减免对方魔法躲避
      33: m_AddAbil.wAgainst := _MIN(High(Word), m_AddAbil.wAgainst + m_ProvisionalAbil[i]);        //Against 抗性
      34: m_AddAbil.btThump2 := _MIN(High(byte), m_AddAbil.btThump2 + m_ProvisionalAbil[i]);        //双倍暴击
      35: m_AddAbil.dwGC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.dwGC) + m_ProvisionalAbil[i]), hiword(m_AddAbil.dwGC)); //GC1          //妖力
      36: m_AddAbil.dwGC := MakeLong(loword(m_AddAbil.dwGC), _MIN(High(MaxInt), hiword(m_AddAbil.dwGC) + m_ProvisionalAbil[i])); //GC2          //妖力
      37: m_AddAbil.wSacredDamMin := _MIN(High(Word), m_AddAbil.wSacredDamMin + m_ProvisionalAbil[i]); //神圣伤害下限
      38: m_AddAbil.wSacredDamMax := _MIN(High(Word), m_AddAbil.wSacredDamMax + m_ProvisionalAbil[i]); //神圣伤害上限
      39: m_AddAbil.dwSacredThump := _MIN(High(MaxInt), m_AddAbil.dwSacredThump + m_ProvisionalAbil[i]);
      40: m_AddAbil.dwSacredExempt := _MIN(High(MaxInt), m_AddAbil.dwSacredExempt + m_ProvisionalAbil[i]);
      41: m_AddAbil.dwSacredPenetRation := _MIN(High(MaxInt), m_AddAbil.dwSacredPenetRation + m_ProvisionalAbil[i]);
    end;
  end;
end;

procedure TPlayObject.RecalcAddPetAbil;
var
  UserItem                              : pTUserItem;
  StdItem                               : pTStdItem;
begin
  //骑战附加属性
  if m_boRideOn then begin
    if m_boPneuma and (m_PneumaObject <> nil) then begin
      TPlayObject(m_PneumaObject).GetUserItemByMakeIndex(TPlayObject(m_PneumaObject).m_PetInfo[3].nMakeIndex, UserItem);
    end else begin
      GetUserItemByMakeIndex(m_PetInfo[2].nMakeIndex, UserItem);
    end;

    if (UserItem <> nil) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if (StdItem <> nil) and (StdItem.StdMode = 49) and (StdItem.Shape = 51) then begin
        GetAccessory(UserItem^, m_AddAbil);
      end;
    end;
  end;

  //魂佑灵兽属性
  if m_boBeast then begin
    GetUserItemByMakeIndex(m_PetInfo[5].nMakeIndex, UserItem);
    if (UserItem <> nil) then begin
      StdItem := UserEngine.GetStdItem(UserItem.wIndex);
      if (StdItem <> nil) and (StdItem.StdMode = 49) and (StdItem.Shape = 51) then begin
        GetAccessory(UserItem^, m_AddAbil);
      end;
    end;
  end;
end;

procedure TPlayObject.RecalcAddSuiteAbil(Idx: Integer; boPercent: Boolean);
var
  SuiteAbility                          : pTSuiteAbility;
begin
  SuiteAbility := UserEngine.GetSuiteAbility(Idx);
  if (SuiteAbility <> nil) then begin
    if boPercent then begin
      m_AddAbil.dwHP := _MIN(MAXHUMHP, m_AddAbil.dwHP + Round(m_Abil.dwMaxHP * SuiteAbility.HP / 100));
      m_AddAbil.dwMP := _MIN(MAXHUMMP, m_AddAbil.dwMP + Round(m_Abil.dwMaxMP * SuiteAbility.MP / 100));
      m_AddAbil.wElementForceMax := _MIN(High(MaxInt), m_AddAbil.wElementForceMax + Round(m_Abil.wElementForceMax * SuiteAbility.EF / 100));
      m_AddAbil.wAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wAC) + Round(loword(m_Abil.AC) * (100 + SuiteAbility.AC) / 100)), hiword(m_AddAbil.wAC));
      m_AddAbil.wAC := MakeLong(loword(m_AddAbil.wAC), _MIN(High(MaxInt), hiword(m_AddAbil.wAC) + Round(hiword(m_Abil.AC) * (100 + SuiteAbility.AC2) / 100)));
      m_AddAbil.wMAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMAC) + Round(loword(m_Abil.MAC) * (100 + SuiteAbility.MAC) / 100)), hiword(m_AddAbil.wMAC));
      m_AddAbil.wMAC := MakeLong(loword(m_AddAbil.wMAC), _MIN(High(MaxInt), hiword(m_AddAbil.wMAC) + Round(hiword(m_Abil.MAC) * (100 + SuiteAbility.MAC2) / 100)));
      m_AddAbil.wDC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wDC) + Round(loword(m_Abil.DC) * (100 + SuiteAbility.DC) / 100)), hiword(m_AddAbil.wDC));
      m_AddAbil.wDC := MakeLong(loword(m_AddAbil.wDC), _MIN(High(MaxInt), hiword(m_AddAbil.wDC) + Round(hiword(m_Abil.DC) * (100 + SuiteAbility.DC2) / 100)));
      m_AddAbil.wMC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMC) + Round(loword(m_Abil.MC) * (100 + SuiteAbility.MC) / 100)), hiword(m_AddAbil.wMC));
      m_AddAbil.wMC := MakeLong(loword(m_AddAbil.wMC), _MIN(High(MaxInt), hiword(m_AddAbil.wMC) + Round(hiword(m_Abil.MC) * (100 + SuiteAbility.MC2) / 100)));
      m_AddAbil.wSC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wSC) + Round(loword(m_Abil.SC) * (100 + SuiteAbility.SC) / 100)), hiword(m_AddAbil.wSC));
      m_AddAbil.wSC := MakeLong(loword(m_AddAbil.wSC), _MIN(High(MaxInt), hiword(m_AddAbil.wSC) + Round(hiword(m_Abil.SC) * (100 + SuiteAbility.SC2) / 100)));
      m_AddAbil.dwGC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.dwGC) + Round(loword(m_Abil.GC) * (100 + SuiteAbility.GC) / 100)), hiword(m_AddAbil.dwGC));
      m_AddAbil.dwGC := MakeLong(loword(m_AddAbil.dwGC), _MIN(High(MaxInt), hiword(m_AddAbil.dwGC) + Round(hiword(m_Abil.GC) * (100 + SuiteAbility.GC2) / 100)));

      m_AddAbil.wHitPoint := Round(m_AddAbil.wHitPoint * (100 + SuiteAbility.HitPoint) / 100);
      m_AddAbil.wSpeedPoint := Round(m_AddAbil.wSpeedPoint * (100 + SuiteAbility.SpeedPoint) / 100);
      m_AddAbil.btMagicNicety := Round(m_AddAbil.btMagicNicety * (100 + SuiteAbility.MagicNicety) / 100);
      m_AddAbil.wAntiMagic := Round(m_AddAbil.wAntiMagic * (100 + SuiteAbility.AntiMagic) / 100);
      m_AddAbil.btPoisonNicety := Round(m_AddAbil.btPoisonNicety * (100 + SuiteAbility.PoisonNicety) / 100);
      m_AddAbil.wAntiPoison := Round(m_AddAbil.wAntiPoison * (100 + SuiteAbility.AntiPoison) / 100);
      m_AddAbil.wHealthRecover := Round(m_AddAbil.wHealthRecover * (100 + SuiteAbility.HealthRecover) / 100);
      m_AddAbil.wSpellRecover := Round(m_AddAbil.wSpellRecover * (100 + SuiteAbility.SpellRecover) / 100);
      m_AddAbil.btVampirePoint := Round(m_AddAbil.btVampirePoint * (100 + SuiteAbility.VampirePoint) / 100);
      m_AddAbil.btVampireRate := _MIN(100, Round(m_AddAbil.btVampireRate * (100 + SuiteAbility.VampireRate) / 100));
      m_AddAbil.btLuck := Round(m_AddAbil.btLuck * (100 + SuiteAbility.Luck) / 100);

      m_AddAbil.btShiftDamage := m_AddAbil.btShiftDamage + Round(m_Abil.btShiftDamage * (100 + SuiteAbility.ShiftDamage) / 100);
      m_AddAbil.btReflexDamage := m_AddAbil.btReflexDamage + Round(m_Abil.btReflexDamage * (100 + SuiteAbility.ReflexDamage) / 100);
      m_AddAbil.wPetFelementPoint[0] := m_AddAbil.wPetFelementPoint[0] + Round(m_Abil.wPetFelementAbil[0] * (100 + SuiteAbility.Gold) / 100);
      m_AddAbil.wPetFelementPoint[1] := m_AddAbil.wPetFelementPoint[1] + Round(m_Abil.wPetFelementAbil[1] * (100 + SuiteAbility.Wood) / 100);
      m_AddAbil.wPetFelementPoint[2] := m_AddAbil.wPetFelementPoint[2] + Round(m_Abil.wPetFelementAbil[2] * (100 + SuiteAbility.Soil) / 100);
      m_AddAbil.wPetFelementPoint[3] := m_AddAbil.wPetFelementPoint[3] + Round(m_Abil.wPetFelementAbil[3] * (100 + SuiteAbility.Water) / 100);
      m_AddAbil.wPetFelementPoint[4] := m_AddAbil.wPetFelementPoint[4] + Round(m_Abil.wPetFelementAbil[4] * (100 + SuiteAbility.Fire) / 100);
      m_AddAbil.btThump := m_AddAbil.btThump + Round(m_Abil.btThump * (100 + SuiteAbility.Thump) / 100);
      m_AddAbil.btReduceAC := m_AddAbil.btReduceAC + Round(m_Abil.btReduceAC * (100 + SuiteAbility.ReduceAC) / 100);
      m_AddAbil.btReduceMAC := m_AddAbil.btReduceMAC + Round(m_Abil.btReduceMAC * (100 + SuiteAbility.ReduceMAC) / 100);
      m_AddAbil.btReduceSpeedPoint := m_AddAbil.btReduceSpeedPoint + Round(m_Abil.btReduceSpeedPoint * (100 + SuiteAbility.ReduceSpeedPoint) / 100);
      m_AddAbil.btReduceAntiMagic := m_AddAbil.btReduceAntiMagic + Round(m_Abil.btReduceAntiMagic * (100 + SuiteAbility.ReduceAntiMagic) / 100);
      m_AddAbil.wAgainst := m_AddAbil.wAgainst + Round(m_Abil.wAgainst * (100 + SuiteAbility.Against) / 100);
      m_AddAbil.wZazen2ExpRate := m_AddAbil.wZazen2ExpRate + Round(m_Abil.wZazen2ExpRate * (100 + SuiteAbility.Zazen2ExpRate) / 100);

      m_AddAbil.btBreakShield := m_AddAbil.btBreakShield + Round(m_Abil.btBreakShield * (100 + SuiteAbility.BreakShield) / 100);
      m_AddAbil.btShieldPower := m_AddAbil.btShieldPower + Round(m_Abil.btShieldPower * (100 + SuiteAbility.ShieldPower) / 100);
      m_AddAbil.btBloodAttack := m_AddAbil.btBloodAttack + Round(m_Abil.btBloodAttack * (100 + SuiteAbility.BloodAttack) / 100);
      m_AddAbil.btBloodDefense := m_AddAbil.btBloodDefense + Round(m_Abil.btBloodDefense * (100 + SuiteAbility.BloodDefense) / 100);
      m_AddAbil.btSacredArmor := m_AddAbil.btSacredArmor + Round(m_Abil.btSacredArmor * (100 + SuiteAbility.SacredArmor) / 100);
      m_AddAbil.btDevilGuard := m_AddAbil.btDevilGuard + Round(m_Abil.btDevilGuard * (100 + SuiteAbility.DevilGuard) / 100);
      m_AddAbil.btNatureGuard := m_AddAbil.btNatureGuard + Round(m_Abil.btNatureGuard * (100 + SuiteAbility.NatureGuard) / 100);
      m_AddAbil.btFightWill := m_AddAbil.btFightWill + Round(m_Abil.btFightWill * (100 + SuiteAbility.FightWill) / 100);
      m_AddAbil.wSacredDamMin := m_AddAbil.wSacredDamMin + Round(m_Abil.wSacredDamMin * (100 + SuiteAbility.SacredDamMin) / 100);
      m_AddAbil.wSacredDamMax := m_AddAbil.wSacredDamMax + Round(m_Abil.wSacredDamMax * (100 + SuiteAbility.SacredDamMax) / 100);
      m_AddAbil.btPowerRate := m_AddAbil.btPowerRate + Round(100 * (100 + SuiteAbility.PowerRate) / 100); //读取攻击倍数
      m_AddAbil.btDefenceRate := m_AddAbil.btDefenceRate + Round(100 * (100 + SuiteAbility.DefenceRate) / 100); //读取防御倍数
    end else begin
      m_AddAbil.dwHP := _MIN(MAXHUMHP, m_AddAbil.dwHP + SuiteAbility.HP);
      m_AddAbil.dwMP := _MIN(MAXHUMMP, m_AddAbil.dwMP + SuiteAbility.MP);
      m_AddAbil.wElementForceMax := _MIN(High(MaxInt), m_AddAbil.wElementForceMax + SuiteAbility.EF);
      m_AddAbil.wDC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wDC) + SuiteAbility.DC), _MIN(High(MaxInt), hiword(m_AddAbil.wDC) + SuiteAbility.DC2));
      m_AddAbil.wMC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMC) + SuiteAbility.MC), _MIN(High(MaxInt), hiword(m_AddAbil.wMC) + SuiteAbility.MC2));
      m_AddAbil.wSC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wSC) + SuiteAbility.SC), _MIN(High(MaxInt), hiword(m_AddAbil.wSC) + SuiteAbility.SC2));
      m_AddAbil.dwGC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.dwGC) + SuiteAbility.GC), _MIN(High(MaxInt), hiword(m_AddAbil.dwGC) + SuiteAbility.GC2));
      m_AddAbil.wAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wAC) + SuiteAbility.AC), _MIN(High(MaxInt), hiword(m_AddAbil.wAC) + SuiteAbility.AC2));
      m_AddAbil.wMAC := MakeLong(_MIN(High(MaxInt), loword(m_AddAbil.wMAC) + SuiteAbility.MAC), _MIN(High(MaxInt), hiword(m_AddAbil.wMAC) + SuiteAbility.MAC2));
      m_AddAbil.wHitPoint := _MIN(High(MaxInt), m_AddAbil.wHitPoint + SuiteAbility.HitPoint);
      m_AddAbil.wSpeedPoint := _MIN(High(MaxInt), m_AddAbil.wSpeedPoint + SuiteAbility.SpeedPoint);
      m_AddAbil.btMagicNicety := _MIN(High(MaxInt), m_AddAbil.btMagicNicety + SuiteAbility.MagicNicety);
      m_AddAbil.wAntiMagic := _MIN(High(MaxInt), m_AddAbil.wAntiMagic + SuiteAbility.AntiMagic);
      m_AddAbil.btPoisonNicety := _MIN(High(MaxInt), m_AddAbil.btPoisonNicety + SuiteAbility.PoisonNicety);
      m_AddAbil.wAntiPoison := _MIN(High(MaxInt), m_AddAbil.wAntiPoison + SuiteAbility.AntiPoison);
      m_AddAbil.wHealthRecover := _MIN(High(word), m_AddAbil.wHealthRecover + SuiteAbility.HealthRecover);
      m_AddAbil.wSpellRecover := _MIN(High(word), m_AddAbil.wSpellRecover + SuiteAbility.SpellRecover);
      m_AddAbil.btVampirePoint := _MIN(High(byte), m_AddAbil.btVampirePoint + SuiteAbility.VampirePoint);
      m_AddAbil.btVampireRate := _MIN(High(byte), m_AddAbil.btVampireRate + SuiteAbility.VampireRate);
      m_AddAbil.btLuck := _MIN(High(byte), m_AddAbil.btLuck + SuiteAbility.Luck);
      m_AddAbil.btShiftDamage := _MIN(High(byte), m_AddAbil.btShiftDamage + SuiteAbility.ShiftDamage);
      m_AddAbil.btReflexDamage := _MIN(High(byte), m_AddAbil.btReflexDamage + SuiteAbility.ReflexDamage);
      m_AddAbil.wPetFelementPoint[0] := _MIN(High(word), m_AddAbil.wPetFelementPoint[0] + SuiteAbility.Gold);
      m_AddAbil.wPetFelementPoint[1] := _MIN(High(word), m_AddAbil.wPetFelementPoint[1] + SuiteAbility.Wood);
      m_AddAbil.wPetFelementPoint[2] := _MIN(High(word), m_AddAbil.wPetFelementPoint[2] + SuiteAbility.Soil);
      m_AddAbil.wPetFelementPoint[3] := _MIN(High(word), m_AddAbil.wPetFelementPoint[3] + SuiteAbility.Water);
      m_AddAbil.wPetFelementPoint[4] := _MIN(High(word), m_AddAbil.wPetFelementPoint[4] + SuiteAbility.Fire);

      m_AddAbil.btThump := _MIN(High(word), m_AddAbil.btThump + SuiteAbility.Thump);
      m_AddAbil.btReduceAC := _MIN(High(Byte), m_AddAbil.btReduceAC + SuiteAbility.ReduceAC);
      m_AddAbil.btReduceMAC := _MIN(High(Byte), m_AddAbil.btReduceMAC + SuiteAbility.ReduceMAC);
      m_AddAbil.btReduceSpeedPoint := _MIN(High(Byte), m_AddAbil.btReduceSpeedPoint + SuiteAbility.ReduceSpeedPoint);
      m_AddAbil.btReduceAntiMagic := _MIN(High(Byte), m_AddAbil.btReduceAntiMagic + SuiteAbility.ReduceAntiMagic);
      m_AddAbil.wAgainst := _MIN(High(word), m_AddAbil.wAgainst + SuiteAbility.Against);
      m_AddAbil.wZazen2ExpRate := _MIN(High(word), m_AddAbil.wZazen2ExpRate + SuiteAbility.Zazen2ExpRate);

      m_AddAbil.btBreakShield := _MIN(High(byte), m_AddAbil.btBreakShield + SuiteAbility.BreakShield);
      m_AddAbil.btShieldPower := _MIN(High(byte), m_AddAbil.btShieldPower + SuiteAbility.ShieldPower);
      m_AddAbil.btBloodAttack := _MIN(High(byte), m_AddAbil.btBloodAttack + SuiteAbility.BloodAttack);
      m_AddAbil.btBloodDefense := _MIN(High(byte), m_AddAbil.btBloodDefense + SuiteAbility.BloodDefense);
      m_AddAbil.btSacredArmor := _MIN(High(byte), m_AddAbil.btSacredArmor + SuiteAbility.SacredArmor);
      m_AddAbil.btDevilGuard := _MIN(High(byte), m_AddAbil.btDevilGuard + SuiteAbility.DevilGuard);
      m_AddAbil.btNatureGuard := _MIN(High(byte), m_AddAbil.btNatureGuard + SuiteAbility.NatureGuard);
      m_AddAbil.btFightWill := _MIN(High(byte), m_AddAbil.btFightWill + SuiteAbility.FightWill);
      m_AddAbil.wSacredDamMin := _MIN(High(Integer), m_AddAbil.wSacredDamMin + SuiteAbility.SacredDamMin);
      m_AddAbil.wSacredDamMax := _MIN(High(Integer), m_AddAbil.wSacredDamMax + SuiteAbility.SacredDamMax);
      m_AddAbil.btPowerRate := _MIN(High(byte), m_AddAbil.btPowerRate + SuiteAbility.PowerRate);
      m_AddAbil.btDefenceRate := _MIN(High(byte), m_AddAbil.btDefenceRate + SuiteAbility.DefenceRate);
    end;

    if CheckSPCode(SuiteAbility.Special, 0) then m_boParalysis := True;
    if CheckSPCode(SuiteAbility.Special, 1) then m_boMagicShield := True;
    if CheckSPCode(SuiteAbility.Special, 2) then m_boRevival := True;
    if CheckSPCode(SuiteAbility.Special, 3) then m_boMuscleRing := True;
    if CheckSPCode(SuiteAbility.Special, 4) then m_boFastTrain := True;
    if CheckSPCode(SuiteAbility.Special, 5) then m_boProbeNecklace := True;
    if CheckSPCode(SuiteAbility.Special, 6) then m_boHideMode := True;
    if CheckSPCode(SuiteAbility.Special, 7) then m_boUnParalysis := True;
    if CheckSPCode(SuiteAbility.Special, 8) then m_boUnMagicShield := True;
    if CheckSPCode(SuiteAbility.Special, 9) then m_boUnRevival := True;
    if CheckSPCode(SuiteAbility.Special, 10) then m_boParalysisEx := True;
    if CheckSPCode(SuiteAbility.Special, 11) then m_boMagicShieldEx := True;
    if CheckSPCode(SuiteAbility.Special, 12) then m_boRevivalEx := True;
    if CheckSPCode(SuiteAbility.Special, 13) then m_boNoDropUseItem := True;
    if CheckSPCode(SuiteAbility.Special, 14) then m_boNoDropItem := True;
    if CheckSPCode(SuiteAbility.Special, 15) then m_boMcParalysis := True;
  end;
end;

procedure TPlayObject.SendBroadVehicle(btCreatorType: Byte; VehicleExp: TVehicleExp);
var
  i, II, nUseTeam                       : Integer;
  boCreator                             : Boolean;
  btState                               : Byte;
  sMemBer                               : string;
  GuildVehicle                          : pTGuildVehicle;
begin
  g_SmallPacketManage.Init;
  if btCreatorType = 0 then begin
    g_SmallPacketManage.FillWrite(29, 0);
  end else begin
    g_SmallPacketManage.WriteByte(3);
    if g_GuildDartList.Count > 0 then begin
      for I := 0 to g_GuildDartList.Count - 1 do begin
        boCreator := False;
        btState := 0;
        GuildVehicle := g_GuildDartList.Items[i];
        for II := 0 to 2 do begin
          if CompareText(m_sCharName, GuildVehicle.sMember[II].UserName) = 0 then begin
            boCreator := True;
            nUseTeam := GuildVehicle.nTeam;
            btState := GuildVehicle.btState;
          end;
        end;
      end;
      if (boCreator) and (btState = 1) then begin
        g_SmallPacketManage.WriteByte(0);
        g_SmallPacketManage.WriteString('running', SizeOf('running'));
        g_SmallPacketManage.WriteByte(0);
      end else g_SmallPacketManage.WriteWord(0);

      g_SmallPacketManage.WriteInteger(g_GuildDartList.Count);
      for I := 0 to g_GuildDartList.Count - 1 do begin
        GuildVehicle := g_GuildDartList.Items[i];
        g_SmallPacketManage.WriteInteger(GuildVehicle.nTeam);
      end;

      g_SmallPacketManage.WriteInteger(g_GuildDartList.Count);
      for I := 0 to g_GuildDartList.Count - 1 do begin
        GuildVehicle := g_GuildDartList.Items[i];
        sMemBer := Format('%s#%d#%s', [GuildVehicle.sMember[0].UserName, GuildVehicle.sMember[0].btType, GuildVehicle.sGuildName]);
        g_SmallPacketManage.WriteString(sMemBer, SizeOf(sMemBer));
        g_SmallPacketManage.WriteByte(0);
      end;

      g_SmallPacketManage.WriteInteger(g_GuildDartList.Count);
      for I := 0 to g_GuildDartList.Count - 1 do begin
        GuildVehicle := g_GuildDartList.Items[i];
        g_SmallPacketManage.WriteInteger(GuildVehicle.nMemberCount);
      end;

      g_SmallPacketManage.WriteInteger(g_GuildDartList.Count);
      for I := 0 to g_GuildDartList.Count - 1 do begin
        GuildVehicle := g_GuildDartList.Items[i];
        g_SmallPacketManage.WriteInteger(GuildVehicle.nMaxMember);
      end;

      g_SmallPacketManage.WriteInteger(g_GuildDartList.Count);
      for I := 0 to g_GuildDartList.Count - 1 do begin
        GuildVehicle := g_GuildDartList.Items[i];
        g_SmallPacketManage.WriteInteger(GuildVehicle.btFullStart);
      end;

      if boCreator then g_SmallPacketManage.WriteInteger(nUseTeam)
      else g_SmallPacketManage.WriteInteger(0);
      g_SmallPacketManage.WriteWord(0);
    end else g_SmallPacketManage.FillWrite(28, 0);
  end;

  g_SmallPacketManage.WriteInteger(3);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[0] * 10000);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[1] * 10000);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[2] * 10000);
  g_SmallPacketManage.WriteInteger(3);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[3] * 10000);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[4] * 10000);
  g_SmallPacketManage.WriteInteger(VehicleExp.nExp[5] * 10000);

  if btCreatorType = 0 then begin
    g_SmallPacketManage.FillWrite(12, 0);
  end else begin
    if boCreator then begin
      GuildVehicle := g_GuildDartList.Items[nUseTeam - 1];
      g_SmallPacketManage.WriteInteger(GuildVehicle.nMemBerCount);
      for II := 0 to 2 do begin
        if (GuildVehicle.nMemBerCount > II) and (GuildVehicle.sMember[II].UserName <> '') then begin
          g_SmallPacketManage.WriteString(GuildVehicle.sMember[II].UserName, SizeOf(GuildVehicle.sMember[II].UserName));
          g_SmallPacketManage.WriteByte(0);
        end;
      end;
      g_SmallPacketManage.WriteInteger(GuildVehicle.nMemBerCount);
      for II := 0 to 2 do begin
        if (GuildVehicle.nMemBerCount > II) and (GuildVehicle.sMember[II].UserName <> '') then
          g_SmallPacketManage.WriteInteger(GuildVehicle.sMember[II].btJob);
      end;
      g_SmallPacketManage.WriteInteger(GuildVehicle.nMemBerCount);
      for II := 0 to 2 do begin
        if (GuildVehicle.nMemBerCount > II) and (GuildVehicle.sMember[II].UserName <> '') then
          g_SmallPacketManage.WriteInteger(GuildVehicle.sMember[II].nLevel);
      end;
    end else g_SmallPacketManage.FillWrite(12, 0);
  end;

  SendDefMessage(2417, Integer(Self), 0, 0, 0, g_SmallPacketManage.GetMsg(), True);
end;

//修复铁血神技顺序图标错乱的问题


procedure TPlayObject.SendWishAwardInfo();
var
  i, ii, nRandSeed, nAward, n14         : Integer;
  SetRadom                              : TRandomEngine;
  sAwardName                            : string;
  nAwardCount, nCount                   : Integer;
begin
  ExecuteScript(g_FunctionNPC, '@_许愿_开始许愿');
  try
    nRandSeed := StrToIntDef(g_FunctionNPC.GetPlayObjectInfo(TPlayObject(Self),
      UserEngine.WishAward.nRandSeed), 0);
    nAward := Random(30);
    SetRadom := TRandomEngine.Create;
    SetRadom.MinNumber := 1;
    SetRadom.MaxNumber := UserEngine.WishAward.nCount;
    SetRadom.Unique := True;
    SetRadom.nRandSeed := nRandSeed;
    g_LargePacketManage.Init;
    g_LargePacketManage.WriteWord($2D);
    g_LargePacketManage.WriteWord($2D);
    g_LargePacketManage.WriteByte(nAward);
    g_LargePacketManage.WriteInteger($1E);
    for I := 1 to 30 do begin
      ii := SetRadom.GetRandom;
      nCount := StrToIntDef(g_FunctionNPC.GetPlayObjectInfo(TPlayObject(Self),
        UserEngine.WishAward.AwardItem[ii].Count), 0);
      n14 := Length(UserEngine.WishAward.AwardItem[ii].ItemName) +
        Length(UserEngine.WishAward.AwardItem[ii].Name) + 10;
      g_LargePacketManage.WriteInteger(n14);
      g_LargePacketManage.WriteString(UserEngine.WishAward.AwardItem[ii].ItemName,
        SizeOf(UserEngine.WishAward.AwardItem[ii].ItemName));
      g_LargePacketManage.WriteByte(0);
      g_LargePacketManage.WriteString(UserEngine.WishAward.AwardItem[ii].Name,
        SizeOf(UserEngine.WishAward.AwardItem[ii].Name));
      g_LargePacketManage.WriteByte(0);
      g_LargePacketManage.WriteWord(nCount);
      g_LargePacketManage.WriteWord(UserEngine.WishAward.AwardItem[ii].nLook);
      if (I - 1) = nAward then begin
        g_LargePacketManage.WriteInteger($01000000);
        sAwardName := UserEngine.WishAward.AwardItem[ii].ItemName;
        nAwardCount := nCount;
      end else
        g_LargePacketManage.WriteInteger(0);
    end;
  finally
    SetRadom.Free;
  end;
  SendDefMessage(2176, integer(Self), 0, 0, 0, g_LargePacketManage.GetMsg, True);
  m_sScriptParam[0] := sAwardName;
  m_sScriptParam[1] := IntToStr(nAwardCount);
  ExecuteScript(g_FunctionNPC, '@_许愿_领取奖励');
end;

end.

回复

使用道具 举报

发表于 2021-11-20 16:55:49 | 显示全部楼层
此帖仅作者可见
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 19:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表