www.pudn.com > M2Engine.rar > Envir1.pas


unit Envir; 
 
interface 
 
uses 
  Windows, SysUtils, Classes, Grobal2; 
type 
  TMapHeader = packed record 
    wWidth: Word; 
    wHeight: Word; 
    sTitle: string[16]; 
    UpdateDate: TDateTime; 
    Reserved: array[0..22] of Char; 
  end; 
  TMapUnitInfo = packed record 
    wBkImg: Word; //32768 $8000 为禁止移动区域 
    wMidImg: Word; 
    wFrImg: Word; 
    btDoorIndex: Byte; //$80 (巩娄), 巩狼 侥喊 牢郸胶 
    btDoorOffset: Byte; //摧腮 巩狼 弊覆狼 惑措 困摹, $80 (凯覆/摧塞(扁夯)) 
    btAniFrame: Byte; //$80(Draw Alpha) +  橇贰烙 荐 
    btAniTick: Byte; 
    btArea: Byte; //瘤开 沥焊 
    btLight: Byte; //0..1..4 堡盔 瓤苞 
  end; 
  pTMapUnitInfo = ^TMapUnitInfo; 
  TMap = array[0..1000 * 1000 - 1] of TMapUnitInfo; 
  pTMap = ^TMap; 
  TMapCellinfo = record 
    chFlag: Byte; 
    bt1: Byte; 
    bt2: Byte; 
    bt3: Byte; 
    ObjList: TList; 
    boListDisPose: Boolean; 
  end; 
  pTMapCellinfo = ^TMapCellinfo; 
  PTEnvirnoment = ^TEnvirnoment; 
  TEnvirnoment = class 
    sMapName: string; //0x4 
    sMapDesc: string; 
    sMainMapName: string; //0x4 
    sSubMapName: string; //0x4 
    m_boMainMap: Boolean; //0x25 
    MapCellArray: array of TMapCellinfo; //0x0C 
    nMinMap: Integer; //0x10 
    nServerIndex: Integer; //0x14 
    nRequestLevel: Integer; //0x18 进入本地图所需等级 
    m_nWidth: Integer; //0x1C 
    m_nHeight: Integer; //0x20 
    m_boDARK: Boolean; //0x24 
    m_boDAY: Boolean; //0x25 
    m_boDarkness: Boolean; 
    m_boDayLight: Boolean; 
    m_DoorList: TList; //0x28 
    bo2C: Boolean; 
    m_boSAFE: Boolean; //0x2D 
    m_boFightZone: Boolean; //0x2E 
    m_boFight3Zone: Boolean; //0x2F  //行会战争地图 
    m_boQUIZ: Boolean; //0x30 
    m_boNORECONNECT: Boolean; //0x31 
    m_boNEEDHOLE: Boolean; //0x32 
    m_boNORECALL: Boolean; //0x33 
    m_boNOGUILDRECALL: Boolean; 
    m_boNODEARRECALL: Boolean; 
    m_boNOMASTERRECALL: Boolean; 
    m_boNORANDOMMOVE: Boolean; //0x34 
    m_boNODRUG: Boolean; //0x35 
    m_boMINE: Boolean; //0x36 
    m_boNOPOSITIONMOVE: Boolean; //0x37 
    sNoReconnectMap: string; //0x38 
    QuestNPC: TObject; //0x3C 
    nNEEDSETONFlag: Integer; //0x40 
    nNeedONOFF: Integer; //0x44 
    m_QuestList: TList; //0x48 
    m_boRUNHUMAN: Boolean; //可以穿人 
    m_boRUNMON: Boolean; //可以穿怪 
    m_boINCHP: Boolean; //自动加HP值 
    m_boIncGameGold: Boolean; //自动减游戏币 
    m_boINCGAMEPOINT: Boolean; //自动加点 
    m_boDECHP: Boolean; //自动减HP值 
    m_boDecGameGold: Boolean; //自动减游戏币 
    m_boDECGAMEPOINT: Boolean; //自动减点 
    m_boMUSIC: Boolean; //音乐 
    m_boEXPRATE: Boolean; //杀怪经验倍数 
    m_boPKWINLEVEL: Boolean; //PK得等级 
    m_boPKWINEXP: Boolean; //PK得经验 
    m_boPKLOSTLEVEL: Boolean; //PK丢等级 
    m_boPKLOSTEXP: Boolean; //PK丢经验 
    m_nPKWINLEVEL: Integer; //PK得等级数 
    m_nPKLOSTLEVEL: Integer; //PK丢等级 
    m_nPKWINEXP: Integer; //PK得经验数 
    m_nPKLOSTEXP: Integer; //PK丢经验 
    m_nDECHPTIME: Integer; //减HP间隔时间 
    m_nDECHPPOINT: Integer; //一次减点数 
    m_nINCHPTIME: Integer; //加HP间隔时间 
    m_nINCHPPOINT: Integer; //一次加点数 
    m_nDECGAMEGOLDTIME: Integer; //减游戏币间隔时间 
    m_nDecGameGold: Integer; //一次减数量 
    m_nDECGAMEPOINTTIME: Integer; //减游戏点间隔时间 
    m_nDECGAMEPOINT: Integer; //一次减数量 
    m_nINCGAMEGOLDTIME: Integer; //加游戏币间隔时间 
    m_nIncGameGold: Integer; //一次加数量 
    m_nINCGAMEPOINTTIME: Integer; //加游戏币间隔时间 
    m_nINCGAMEPOINT: Integer; //一次加数量 
    m_nMUSICID: Integer; //音乐ID 
    m_nEXPRATE: Integer; //经验倍率 
    m_nMonCount: Integer; 
    m_nHumCount: Integer; 
 
    m_boUnAllowStdItems: Boolean; //是否不允许使用物品 
    m_UnAllowStdItemsList: TGStringList; //不允许使用物品列表 
    m_boAutoMakeMonster: Boolean; 
  private 
    procedure Initialize(nWidth, nHeight: Integer); 
  public 
    constructor Create(); 
    destructor Destroy; override; 
    function AddToMap(nX, nY: Integer; btType: Byte; pRemoveObject: TObject): Pointer; 
    function CanWalk(nX, nY: Integer; boFlag: Boolean): Boolean; 
    function CanWalkOfItem(nX, nY: Integer; boFlag, boItem: Boolean): Boolean; 
    function CanWalkEx(nX, nY: Integer; boFlag: Boolean): Boolean; 
    function CanFly(nSX, nSY, nDX, nDY: Integer): Boolean; 
    function MoveToMovingObject(nCX, nCY: Integer; Cert: TObject; nX, nY: Integer; boFlag: Boolean): Integer; 
    function GetItem(nX, nY: Integer): PTMapItem; 
    function DeleteFromMap(nX, nY: Integer; btType: Byte; pRemoveObject: TObject): Integer; 
    function IsCheapStuff(): Boolean; 
    procedure AddDoorToMap; 
    function AddToMapMineEvent(nX, nY: Integer; nType: Integer; Event: TObject): TObject; 
    function LoadMapData(sMapFile: string): Boolean; 
    function CreateQuest(nFlag, nValue: Integer; s24, s28, s2C: string; boGrouped: Boolean): Boolean; 
    function GetMapCellInfo(nX, nY: Integer; var MapCellInfo: pTMapCellinfo): Boolean; 
    function GetXYObjCount(nX, nY: Integer): Integer; 
    function GetNextPosition(sX, sY, nDir, nFlag: Integer; var snx: Integer; var sny: Integer): Boolean; 
    function sub_4B5FC8(nX, nY: Integer): Boolean; 
    procedure VerifyMapTime(nX, nY: Integer; BaseObject: TObject); 
    function CanSafeWalk(nX, nY: Integer): Boolean; 
    function ArroundDoorOpened(nX, nY: Integer): Boolean; 
    function GetMovingObject(nX, nY: Integer; boFlag: Boolean): Pointer; 
    function GetQuestNPC(BaseObject: TObject; sCharName, sStr: string; boFlag: Boolean): TObject; 
    function GetItemEx(nX, nY: Integer; var nCount: Integer): Pointer; 
    function GetDoor(nX, nY: Integer): pTDoorInfo; 
    function IsValidObject(nX, nY: Integer; nRage: Integer; BaseObject: TObject): Boolean; 
    function GetRangeBaseObject(nX, nY: Integer; nRage: Integer; boFlag: Boolean; BaseObjectList: TList): Integer; 
    function GeTBaseObjects(nX, nY: Integer; boFlag: Boolean; BaseObjectList: TList): Integer; 
    function GetEvent(nX, nY: Integer): TObject; 
    procedure SetMapXYFlag(nX, nY: Integer; boFlag: Boolean); 
    function GetXYHuman(nMapX, nMapY: Integer): Boolean; 
    function GetEnvirInfo(): string; 
    function AllowStdItems(sItemName: string): Boolean; overload; 
    function AllowStdItems(nItemIdx: Integer): Boolean; overload; 
    procedure AddObject(nType: Integer); 
    procedure DelObjectCount(BaseObject: TObject); 
    property MonCount: Integer read m_nMonCount; 
    property HumCount: Integer read m_nHumCount; 
 
  end; 
  TMapManager = class(TGList) //004B52B0 
  private 
  public 
    constructor Create(); 
    destructor Destroy; override; 
    procedure LoadMapDoor(); 
    function AddMapInfo(sMapName, sMainMapName, sMapDesc: string; nServerNumber: Integer; MapFlag: pTMapFlag; QuestNPC: TObject): TEnvirnoment; 
    function GetMapInfo(nServerIdx: Integer; sMapName: string): TEnvirnoment; 
    function AddMapRoute(sSMapNO: string; nSMapX, nSMapY: Integer; sDMapNO: string; nDMapX, nDMapY: Integer): Boolean; 
    function GetMapOfServerIndex(sMapName: string): Integer; 
    function FindMap(sMapName: string): TEnvirnoment; 
    function GetMainMap(Envir: TEnvirnoment): string; 
    procedure ReSetMinMap(); 
    procedure Run(); 
    procedure ProcessMapDoor(); 
    procedure MakeSafePkZone(); 
  end; 
implementation 
 
uses ObjBase, ObjNpc, M2Share, Event, ObjMon, HUtil32, Castle; 
 
{ TEnvirList } 
 
//004B7038 
procedure TMapManager.MakeSafePkZone(); 
var 
  nX, nY: Integer; 
  SafeEvent: TSafeEvent; 
  nMinX, nMaxX, nMinY, nMaxY: Integer; 
  nRange, nType, nTime, nPoint: Integer; 
  I: Integer; 
  StartPoint: pTStartPoint; 
  Envir: TEnvirnoment; 
begin 
  g_StartPointList.Lock; 
  for I := 0 to g_StartPointList.Count - 1 do begin 
    StartPoint := pTStartPoint(g_StartPointList.Objects[I]); 
    if (StartPoint <> nil) and (StartPoint.m_nType > 0) then begin 
      Envir := FindMap(StartPoint.m_sMapName); 
      if Envir <> nil then begin 
        nMinX := StartPoint.m_nCurrX - StartPoint.m_nRange; 
        nMaxX := StartPoint.m_nCurrX + StartPoint.m_nRange; 
        nMinY := StartPoint.m_nCurrY - StartPoint.m_nRange; 
        nMaxY := StartPoint.m_nCurrY + StartPoint.m_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 
              SafeEvent := TSafeEvent.Create(Envir, nX, nY, StartPoint.m_nType); 
              g_EventManager.AddEvent(SafeEvent); 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TMapManager.AddMapInfo(sMapName, sMainMapName, sMapDesc: string; nServerNumber: Integer; MapFlag: pTMapFlag; QuestNPC: TObject): TEnvirnoment; 
var 
  Envir: TEnvirnoment; 
  I: Integer; 
  nStd: Integer; 
  TempList: TStringList; 
begin 
  Result := nil; 
  Envir := TEnvirnoment.Create; 
  Envir.sMapName := sMapName; 
  Envir.sMainMapName := sMainMapName; 
  Envir.sSubMapName := sMapName; 
  Envir.sMapDesc := sMapDesc; 
  if sMainMapName <> '' then Envir.m_boMainMap := True; 
  Envir.nServerIndex := nServerNumber; 
  Envir.m_boSAFE := MapFlag.boSAFE; 
  Envir.m_boFightZone := MapFlag.boFIGHT; 
  Envir.m_boFight3Zone := MapFlag.boFIGHT3; 
  Envir.m_boDARK := MapFlag.boDARK; 
  Envir.m_boDAY := MapFlag.boDAY; 
  Envir.m_boQUIZ := MapFlag.boQUIZ; 
  Envir.m_boNORECONNECT := MapFlag.boNORECONNECT; 
  Envir.m_boNEEDHOLE := MapFlag.boNEEDHOLE; 
  Envir.m_boNORECALL := MapFlag.boNORECALL; 
  Envir.m_boNOGUILDRECALL := MapFlag.boNOGUILDRECALL; 
  Envir.m_boNODEARRECALL := MapFlag.boNODEARRECALL; 
  Envir.m_boNOMASTERRECALL := MapFlag.boNOMASTERRECALL; 
  Envir.m_boNORANDOMMOVE := MapFlag.boNORANDOMMOVE; 
  Envir.m_boNODRUG := MapFlag.boNODRUG; 
  Envir.m_boMINE := MapFlag.boMINE; 
  Envir.m_boNOPOSITIONMOVE := MapFlag.boNOPOSITIONMOVE; 
 
  Envir.m_boRUNHUMAN := MapFlag.boRUNHUMAN; //可以穿人 
  Envir.m_boRUNMON := MapFlag.boRUNMON; //可以穿怪 
  Envir.m_boDECHP := MapFlag.boDECHP; //自动减HP值 
  Envir.m_boINCHP := MapFlag.boINCHP; //自动加HP值 
  Envir.m_boDecGameGold := MapFlag.boDECGAMEGOLD; //自动减游戏币 
  Envir.m_boDECGAMEPOINT := MapFlag.boDECGAMEPOINT; //自动减游戏币 
  Envir.m_boIncGameGold := MapFlag.boINCGAMEGOLD; //自动加游戏币 
  Envir.m_boINCGAMEPOINT := MapFlag.boINCGAMEPOINT; //自动加游戏点 
  Envir.m_boMUSIC := MapFlag.boMUSIC; //音乐 
  Envir.m_boEXPRATE := MapFlag.boEXPRATE; //杀怪经验倍数 
  Envir.m_boPKWINLEVEL := MapFlag.boPKWINLEVEL; //PK得等级 
  Envir.m_boPKWINEXP := MapFlag.boPKWINEXP; //PK得经验 
  Envir.m_boPKLOSTLEVEL := MapFlag.boPKLOSTLEVEL; 
  Envir.m_boPKLOSTEXP := MapFlag.boPKLOSTEXP; 
  Envir.m_nPKWINLEVEL := MapFlag.nPKWINLEVEL; //PK得等级数 
  Envir.m_nPKWINEXP := MapFlag.nPKWINEXP; //PK得经验数 
  Envir.m_nPKLOSTLEVEL := MapFlag.nPKLOSTLEVEL; 
  Envir.m_nPKLOSTEXP := MapFlag.nPKLOSTEXP; 
  Envir.m_nPKWINEXP := MapFlag.nPKWINEXP; //PK得经验数 
  Envir.m_nDECHPTIME := MapFlag.nDECHPTIME; //减HP间隔时间 
  Envir.m_nDECHPPOINT := MapFlag.nDECHPPOINT; //一次减点数 
  Envir.m_nINCHPTIME := MapFlag.nINCHPTIME; //加HP间隔时间 
  Envir.m_nINCHPPOINT := MapFlag.nINCHPPOINT; //一次加点数 
  Envir.m_nDECGAMEGOLDTIME := MapFlag.nDECGAMEGOLDTIME; //减游戏币间隔时间 
  Envir.m_nDecGameGold := MapFlag.nDECGAMEGOLD; //一次减数量 
  Envir.m_nINCGAMEGOLDTIME := MapFlag.nINCGAMEGOLDTIME; //减游戏币间隔时间 
  Envir.m_nIncGameGold := MapFlag.nINCGAMEGOLD; //一次减数量 
  Envir.m_nINCGAMEPOINTTIME := MapFlag.nINCGAMEPOINTTIME; //减游戏币间隔时间 
  Envir.m_nINCGAMEPOINT := MapFlag.nINCGAMEPOINT; //一次减数量 
  Envir.m_nMUSICID := MapFlag.nMUSICID; //音乐ID 
  Envir.m_nEXPRATE := MapFlag.nEXPRATE; //经验倍率 
 
  Envir.sNoReconnectMap := MapFlag.sReConnectMap; 
  Envir.QuestNPC := QuestNPC; 
  Envir.nNEEDSETONFlag := MapFlag.nNEEDSETONFlag; 
  Envir.nNeedONOFF := MapFlag.nNeedONOFF; 
  Envir.m_boAutoMakeMonster := MapFlag.boAutoMakeMonster; 
 
  if (MapFlag.boUnAllowStdItems) and (MapFlag.sUnAllowStdItemsText <> '') then begin 
    Envir.m_boUnAllowStdItems := True; 
    Envir.m_UnAllowStdItemsList := TGStringList.Create; 
    TempList := TStringList.Create; 
    ExtractStrings(['|', '\', '/'], [], PChar(Trim(MapFlag.sUnAllowStdItemsText)), TempList); 
    for I := 0 to TempList.Count - 1 do begin 
      nStd := UserEngine.GetStdItemIdx(Trim(TempList.Strings[I])); 
      if nStd >= 0 then 
        Envir.m_UnAllowStdItemsList.AddObject(Trim(TempList.Strings[I]), TObject(nStd)); 
    end; 
    TempList.Free; 
  end; 
 
  for I := 0 to MiniMapList.Count - 1 do begin 
    if CompareText(MiniMapList.Strings[I], Envir.sMapName) = 0 then begin 
      Envir.nMinMap := Integer(MiniMapList.Objects[I]); 
      break; 
    end; 
  end; 
  if sMainMapName <> '' then begin 
    if Envir.LoadMapData(g_Config.sMapDir + sMainMapName + '.map') then begin 
      Result := Envir; 
      Self.Add(Envir); 
    end else begin 
      MainOutMessage('地图文件 ' + g_Config.sMapDir + sMainMapName + '.map' + ' 未找到!!!'); 
    end; 
  end else begin 
    if Envir.LoadMapData(g_Config.sMapDir + sMapName + '.map') then begin 
      Result := Envir; 
      Self.Add(Envir); 
    end else begin 
      MainOutMessage('地图文件 ' + g_Config.sMapDir + sMapName + '.map' + ' 未找到!!!'); 
    end; 
  end; 
end; 
 
function TMapManager.AddMapRoute(sSMapNO: string; nSMapX, nSMapY: Integer; sDMapNO: string; nDMapX, nDMapY: Integer): Boolean; 
var 
  GateObj: pTGateObj; 
  SEnvir: TEnvirnoment; 
  DEnvir: TEnvirnoment; 
begin 
  Result := False; 
  SEnvir := FindMap(sSMapNO); 
  DEnvir := FindMap(sDMapNO); 
  if (SEnvir <> nil) and (DEnvir <> nil) then begin 
    New(GateObj); 
    GateObj.boFlag := False; 
    GateObj.DEnvir := DEnvir; 
    GateObj.nDMapX := nDMapX; 
    GateObj.nDMapY := nDMapY; 
    SEnvir.AddToMap(nSMapX, nSMapY, OS_GATEOBJECT, TObject(GateObj)); 
    Result := True; 
  end; 
end; 
 
function TEnvirnoment.AddToMap(nX, nY: Integer; btType: Byte; 
  pRemoveObject: TObject): Pointer; 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  MapItem: PTMapItem; 
  I: Integer; 
  nGoldCount: Integer; 
  bo1E: Boolean; 
  btRaceServer: Byte; 
  nCheckCode: Integer; 
resourcestring 
  sExceptionMsg = '[Exception] TEnvirnoment::AddToMap'; 
begin 
  Result := nil; 
  try 
    bo1E := False; 
    if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
      if (MapCellInfo.ObjList = nil) or (MapCellInfo.boListDisPose) then begin 
        MapCellInfo.ObjList := TList.Create; 
        MapCellInfo.boListDisPose := False; 
      end else begin 
        if btType = OS_ITEMOBJECT then begin 
          if PTMapItem(pRemoveObject).Name = sSTRING_GOLDNAME then begin 
            if (MapCellInfo.ObjList <> nil) and (MapCellInfo.ObjList.Count > 0) and (not MapCellInfo.boListDisPose) then begin 
              for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
                OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
                if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
                  if OSObject.btType = OS_ITEMOBJECT then begin 
                    MapItem := PTMapItem(pTOSObject(MapCellInfo.ObjList.Items[I]).CellObj); 
                    if MapItem <> nil then begin 
                      if MapItem.Name = sSTRING_GOLDNAME then begin 
                        nGoldCount := MapItem.Count + PTMapItem(pRemoveObject).Count; 
                        if nGoldCount <= 2000 then begin 
                          MapItem.Count := nGoldCount; 
                          MapItem.Looks := GetGoldShape(nGoldCount); 
                          MapItem.AniCount := 0; 
                          MapItem.Reserved := 0; 
                          OSObject.dwAddTime := GetTickCount(); 
                          Result := MapItem; 
                          bo1E := True; 
                        end; 
                      end; 
                    end; 
                  end; 
                end; 
              end; 
            end; 
          end; 
          if not bo1E and (MapCellInfo.ObjList <> nil) and (MapCellInfo.ObjList.Count >= 5) then begin 
            Result := nil; 
            bo1E := True; 
          end; 
        end; 
        if btType = OS_EVENTOBJECT then begin 
 
        end; 
      end; 
      if not bo1E then begin 
        OSObject := nil; 
        nCheckCode := 0; 
        New(OSObject); 
        nCheckCode := 1; 
        OSObject.btType := btType; 
        OSObject.CellObj := pRemoveObject; 
        OSObject.dwAddTime := GetTickCount(); 
        OSObject.boObjectDisPose := False; 
        MapCellInfo.ObjList.Add(OSObject); 
        nCheckCode := 2; 
        Result := Pointer(pRemoveObject); 
        if (btType = OS_MOVINGOBJECT) and (not TBaseObject(pRemoveObject).m_boAddToMaped) then begin 
          TBaseObject(pRemoveObject).m_boDelFormMaped := False; 
          TBaseObject(pRemoveObject).m_boAddToMaped := True; 
          btRaceServer := TBaseObject(pRemoveObject).m_btRaceServer; 
          if btRaceServer = RC_PLAYOBJECT then Inc(m_nHumCount); 
          if btRaceServer >= RC_ANIMAL then Inc(m_nMonCount); 
        end; 
      end; 
    end; 
  except 
    if (nCheckCode = 1) and (OSObject <> nil) then begin 
      DisPose(OSObject); 
    end; 
    //MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
function TEnvirnoment.AllowStdItems(sItemName: string): Boolean; //是否允许使用物品 
var 
  I: Integer; 
begin 
  Result := True; 
  if (not m_boUnAllowStdItems) or (m_UnAllowStdItemsList = nil) then Exit; 
  m_UnAllowStdItemsList.Lock; 
  try 
    for I := 0 to m_UnAllowStdItemsList.Count - 1 do begin 
      if CompareText(m_UnAllowStdItemsList.Strings[I], sItemName) = 0 then begin 
        Result := False; 
        break; 
      end; 
    end; 
  finally 
    m_UnAllowStdItemsList.UnLock; 
  end; 
end; 
 
function TEnvirnoment.AllowStdItems(nItemIdx: Integer): Boolean; //是否允许使用物品 
var 
  I: Integer; 
begin 
  Result := True; 
  if (not m_boUnAllowStdItems) or (m_UnAllowStdItemsList = nil) then Exit; 
  m_UnAllowStdItemsList.Lock; 
  try 
    for I := 0 to m_UnAllowStdItemsList.Count - 1 do begin 
      if Integer(m_UnAllowStdItemsList.Objects[I]) = nItemIdx then begin 
        Result := False; 
        break; 
      end; 
    end; 
  finally 
    m_UnAllowStdItemsList.UnLock; 
  end; 
end; 
 
procedure TEnvirnoment.AddDoorToMap(); 
var 
  I: Integer; 
  Door: pTDoorInfo; 
begin 
  for I := 0 to m_DoorList.Count - 1 do begin 
    Door := m_DoorList.Items[I]; 
    AddToMap(Door.nX, Door.nY, OS_DOOR, TObject(Door)); 
  end; 
end; 
 
function TEnvirnoment.GetMapCellInfo(nX, nY: Integer; var MapCellInfo: pTMapCellinfo): Boolean; //004B57D8 
begin 
  try 
    if (nX >= 0) and (nX < m_nWidth) and (nY >= 0) and (nY < m_nHeight) then begin 
      MapCellInfo := @MapCellArray[nX * m_nHeight + nY]; 
      Result := True; 
    end else begin 
      Result := False; 
    end; 
  except 
    Result := False; 
  end; 
end; 
 
function TEnvirnoment.MoveToMovingObject(nCX, nCY: Integer; Cert: TObject; nX, nY: Integer; boFlag: Boolean): Integer; //004B612C 
var 
  MapCellInfo: pTMapCellinfo; 
  BaseObject: TBaseObject; 
  OSObject: pTOSObject; 
  I: Integer; 
  bo1A: Boolean; 
  nCheckCode: Integer; 
resourcestring 
  sExceptionMsg = '[Exception] TEnvirnoment::MoveToMovingObject'; 
label 
  Loop, Over; 
begin 
  Result := 0; 
  try 
    bo1A := True; 
    nCheckCode := 0; 
    if not boFlag and GetMapCellInfo(nX, nY, MapCellInfo) then begin 
      nCheckCode := 1; 
      if (MapCellInfo <> nil) and (not MapCellInfo.boListDisPose) then begin 
        if MapCellInfo.chFlag = 0 then begin 
          if (MapCellInfo.ObjList <> nil) and (MapCellInfo.ObjList.Count > 0) then begin 
            nCheckCode := 2; 
            for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
              nCheckCode := 3; 
              OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
              nCheckCode := 4; 
              if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
                if OSObject.btType = OS_MOVINGOBJECT then begin 
                  if OSObject.CellObj <> nil then begin 
                    BaseObject := TBaseObject(pTOSObject(OSObject.CellObj)); 
                    nCheckCode := 5; 
                    if BaseObject <> nil then begin 
                      if not BaseObject.m_boGhost 
                        and BaseObject.bo2B9 
                        and not BaseObject.m_boDeath 
                        and not BaseObject.m_boFixedHideMode 
                        and not BaseObject.m_boObMode then begin 
                        bo1A := False; 
                        break; 
                      end; 
                    end; 
                  end; 
                end; 
              end; 
            end; 
          end; 
        end else begin //   if MapCellInfo.chFlag = 0 then begin 
          Result := -1; 
          bo1A := False; 
        end; 
      end; 
    end; 
    if bo1A then begin 
      if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo <> nil) and (MapCellInfo.chFlag <> 0) and (not MapCellInfo.boListDisPose) then begin 
        Result := -1; 
      end else begin 
        if GetMapCellInfo(nCX, nCY, MapCellInfo) and (MapCellInfo <> nil) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
          I := 0; 
          while (True) do begin 
            if MapCellInfo.ObjList.Count <= I then break; 
            if MapCellInfo.ObjList.Count <= 0 then break; 
            OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
            if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
              nCheckCode := 6; 
              if OSObject.btType = OS_MOVINGOBJECT then begin 
                nCheckCode := 7; 
                if (TBaseObject(OSObject.CellObj) <> nil) and (TBaseObject(OSObject.CellObj) = TBaseObject(Cert)) and (TBaseObject(Cert) <> nil) then begin 
                  if not OSObject.boObjectDisPose then begin 
                    OSObject.boObjectDisPose := True; 
                    try 
                      DisPose(OSObject); 
                    except 
                      OSObject := nil; 
                    end; 
                  end; 
                  MapCellInfo.ObjList.Delete(I); 
                  if MapCellInfo.ObjList.Count > 0 then Continue; 
                  nCheckCode := 11; 
                  if not MapCellInfo.boListDisPose then begin 
                    MapCellInfo.boListDisPose := True; 
                    MapCellInfo.ObjList.Free; 
                    MapCellInfo.ObjList := nil; 
                    nCheckCode := 12; 
                  end; 
                  break; 
                end; 
              end; 
            end; 
            Inc(I); 
          end; 
        end; 
        nCheckCode := 13; 
        if GetMapCellInfo(nX, nY, MapCellInfo) then begin 
          if (MapCellInfo.ObjList = nil) or (MapCellInfo.boListDisPose) then begin 
            MapCellInfo.ObjList := TList.Create; 
            MapCellInfo.boListDisPose := False; 
          end; 
          New(OSObject); 
          OSObject.btType := OS_MOVINGOBJECT; 
          OSObject.CellObj := Cert; 
          OSObject.dwAddTime := GetTickCount; 
          OSObject.boObjectDisPose := False; 
          MapCellInfo.ObjList.Add(OSObject); 
          Result := 1; 
        end; 
      end; 
    end; 
  except 
    on E: Exception do begin 
      {MainOutMessage(sExceptionMsg + ' '+IntToStr(nCheckCode)); 
      MainOutMessage(E.Message);} 
    end; 
  end; 
  //  pMapCellInfo = GetMapCellInfo(nX, nY); 
end; 
//====================================================================== 
//检查地图指定座标是否可以移动 
//boFlag  如果为TRUE 则忽略座标上是否有角色 
//返回值 True 为可以移动,False 为不可以移动 
//====================================================================== 
function TEnvirnoment.CanWalk(nX, nY: Integer; boFlag: Boolean): Boolean; //004B5ED0 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
  I: Integer; 
begin 
  Result := False; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
    Result := True; 
    if not boFlag and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) and (MapCellInfo.ObjList.Count > 0) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := MapCellInfo.ObjList.Items[I]; 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if OSObject.btType = OS_MOVINGOBJECT then begin 
            BaseObject := TBaseObject(OSObject.CellObj); 
            if BaseObject <> nil then begin 
              if not BaseObject.m_boGhost 
                and BaseObject.bo2B9 
                and not BaseObject.m_boDeath 
                and not BaseObject.m_boFixedHideMode 
                and not BaseObject.m_boObMode then begin 
                Result := False; 
                break; 
              end; 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
//====================================================================== 
//检查地图指定座标是否可以移动 
//boFlag  如果为TRUE 则忽略座标上是否有角色 
//返回值 True 为可以移动,False 为不可以移动 
//====================================================================== 
function TEnvirnoment.CanWalkOfItem(nX, nY: Integer; boFlag, boItem: Boolean): Boolean; 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
  I: Integer; 
begin 
  Result := True; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
    if (MapCellInfo.ObjList <> nil) and (MapCellInfo.ObjList.Count > 0) and (not MapCellInfo.boListDisPose) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := MapCellInfo.ObjList.Items[I]; 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if not boFlag and (OSObject.btType = OS_MOVINGOBJECT) then begin 
            BaseObject := TBaseObject(OSObject.CellObj); 
            if BaseObject <> nil then begin 
              if not BaseObject.m_boGhost 
                and BaseObject.bo2B9 
                and not BaseObject.m_boDeath 
                and not BaseObject.m_boFixedHideMode 
                and not BaseObject.m_boObMode then begin 
                Result := False; 
                break; 
              end; 
            end; 
          end; 
        end; 
        if not boItem and (OSObject.btType = OS_ITEMOBJECT) then begin 
          Result := False; 
          break; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.CanWalkEx(nX, nY: Integer; boFlag: Boolean): Boolean; 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
  I: Integer; 
  Castle: TUserCastle; 
begin 
  Result := False; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
    Result := True; 
    if not boFlag and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) and (MapCellInfo.ObjList.Count > 0) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := MapCellInfo.ObjList.Items[I]; 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if OSObject.btType = OS_MOVINGOBJECT then begin 
            BaseObject := TBaseObject(OSObject.CellObj); 
            if BaseObject <> nil then begin 
              {//01/25 多城堡 控制 
              if g_Config.boWarDisHumRun and UserCastle.m_boUnderWar and 
                UserCastle.InCastleWarArea(BaseObject.m_PEnvir,BaseObject.m_nCurrX,BaseObject.m_nCurrY) then begin 
              } 
              Castle := g_CastleManager.InCastleWarArea(BaseObject); 
              if g_Config.boWarDisHumRun and (Castle <> nil) and (Castle.m_boUnderWar) then begin 
              end else begin 
                if BaseObject.m_btRaceServer = RC_PLAYOBJECT then begin 
                  if g_Config.boRUNHUMAN or m_boRUNHUMAN then Continue; 
                end else begin 
                  if BaseObject.m_btRaceServer = RC_NPC then begin 
                    if g_Config.boRunNpc then Continue; 
                  end else begin 
                    if BaseObject.m_btRaceServer in [RC_GUARD, RC_ARCHERGUARD] then begin 
                      if g_Config.boRunGuard then Continue; 
                    end else begin 
                      if BaseObject.m_btRaceServer <> 55 then begin //不允许穿过练功师 
                        if g_Config.boRUNMON or m_boRUNMON then Continue; 
                      end; 
                    end; 
                  end; 
                end; 
              end; 
              if not BaseObject.m_boGhost 
                and BaseObject.bo2B9 
                and not BaseObject.m_boDeath 
                and not BaseObject.m_boFixedHideMode 
                and not BaseObject.m_boObMode then begin 
                Result := False; 
                break; 
              end; 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
constructor TMapManager.Create; 
begin 
 
  inherited Create; 
end; 
 
destructor TMapManager.Destroy; 
var 
  I: Integer; 
begin 
  for I := 0 to Count - 1 do begin 
    TEnvirnoment(Items[I]).Free; 
  end; 
 
  inherited; 
end; 
 
function TMapManager.GetMainMap(Envir: TEnvirnoment): string; 
begin 
  if Envir.m_boMainMap then Result := Envir.sMainMapName 
  else Result := Envir.sMapName; 
end; 
 
function TMapManager.FindMap(sMapName: string): TEnvirnoment; 
var 
  Map: TEnvirnoment; 
  I: Integer; 
begin 
  Result := nil; 
  Lock; 
  try 
    for I := 0 to Count - 1 do begin 
      Map := TEnvirnoment(Items[I]); 
      if Map <> nil then begin 
        if CompareText(Map.sMapName, sMapName) = 0 then begin 
          Result := Map; 
          break; 
        end; 
      end; 
    end; 
  finally 
    UnLock; 
  end; 
end; 
 
function TMapManager.GetMapInfo(nServerIdx: Integer; sMapName: string): TEnvirnoment; 
var 
  I: Integer; 
  Envir: TEnvirnoment; 
begin 
  Result := nil; 
  Lock; 
  try 
    for I := 0 to Count - 1 do begin 
      Envir := Items[I]; 
      if Envir <> nil then begin 
        if (Envir.nServerIndex = nServerIdx) and (CompareText(Envir.sMapName, sMapName) = 0) then begin 
          Result := Envir; 
          break; 
        end; 
      end; 
    end; 
  finally 
    UnLock; 
  end; 
end; 
 
function TEnvirnoment.DeleteFromMap(nX, nY: Integer; btType: Byte; 
  pRemoveObject: TObject): Integer; 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  n18: Integer; 
  btRaceServer: Byte; 
resourcestring 
  sExceptionMsg1 = '[Exception] TEnvirnoment::DeleteFromMap -> Except 1 ** %d'; 
  sExceptionMsg2 = '[Exception] TEnvirnoment::DeleteFromMap -> Except 2 ** %d'; 
begin 
  Result := -1; 
  try 
    if GetMapCellInfo(nX, nY, MapCellInfo) then begin 
      if MapCellInfo <> nil then begin 
        try 
          if (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) and (MapCellInfo.ObjList.Count > 0) then begin 
            n18 := 0; 
            while (True) do begin 
              if MapCellInfo.ObjList.Count <= n18 then break; 
              if MapCellInfo.ObjList.Count <= 0 then break; 
              OSObject := pTOSObject(MapCellInfo.ObjList.Items[n18]); 
              if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
                if (OSObject.btType = btType) and (OSObject.CellObj = pRemoveObject) then begin 
                  if not OSObject.boObjectDisPose then begin 
                    OSObject.boObjectDisPose := True; 
                    try 
                      DisPose(OSObject); 
                    except 
                      OSObject := nil; 
                    end; 
                  end; 
                  MapCellInfo.ObjList.Delete(n18); 
                  Result := 1; 
                  //减地图人物怪物计数 
                  if (btType = OS_MOVINGOBJECT) and (not TBaseObject(pRemoveObject).m_boDelFormMaped) then begin 
                    TBaseObject(pRemoveObject).m_boDelFormMaped := True; 
                    TBaseObject(pRemoveObject).m_boAddToMaped := False; 
                    btRaceServer := TBaseObject(pRemoveObject).m_btRaceServer; 
                    if btRaceServer = RC_PLAYOBJECT then Dec(m_nHumCount); 
                    if btRaceServer >= RC_ANIMAL then Dec(m_nMonCount); 
                  end; 
 
                  if MapCellInfo.ObjList.Count > 0 then Continue; 
                  if not MapCellInfo.boListDisPose then begin 
                    MapCellInfo.boListDisPose := True; 
                    MapCellInfo.ObjList.Free; 
                    MapCellInfo.ObjList := nil; 
                  end; 
                  break; 
                  //Jacky 处理防止内存泄露 有待换上 
                 { if MapCellInfo.ObjList.Count <= 0 then begin 
                    MapCellInfo.ObjList.Free; 
                    MapCellInfo.ObjList:=nil; 
                    break; 
                  end; } 
                end 
              end else begin 
                MapCellInfo.ObjList.Delete(n18); 
                if MapCellInfo.ObjList.Count > 0 then Continue; 
                if not MapCellInfo.boListDisPose then begin 
                  MapCellInfo.boListDisPose := True; 
                  MapCellInfo.ObjList.Free; 
                  MapCellInfo.ObjList := nil; 
                end; 
                break; 
              end; 
              Inc(n18); 
            end; 
          end else begin 
            Result := -2; 
          end; 
        except 
          OSObject := nil; 
          //MainOutMessage(format(sExceptionMsg1, [btType])); 
        end; 
      end else Result := -3; 
    end else Result := 0; 
  except 
    //MainOutMessage(format(sExceptionMsg2, [btType])); 
  end; 
end; 
 
function TEnvirnoment.GetItem(nX, nY: Integer): PTMapItem; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  Result := nil; 
  bo2C := False; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
    bo2C := True; 
    if (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) and (MapCellInfo.ObjList.Count > 0) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if OSObject.btType = OS_ITEMOBJECT then begin 
            Result := PTMapItem(OSObject.CellObj); 
            Exit; 
          end; 
          if OSObject.btType = OS_GATEOBJECT then 
            bo2C := False; 
          if OSObject.btType = OS_MOVINGOBJECT then begin 
            BaseObject := TBaseObject(OSObject.CellObj); 
            if BaseObject <> nil then begin 
              if not BaseObject.m_boDeath then 
                bo2C := False; 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TMapManager.GetMapOfServerIndex(sMapName: string): Integer; 
var 
  I: Integer; 
  Envir: TEnvirnoment; 
begin 
  Result := 0; 
  Lock; 
  try 
    for I := 0 to Count - 1 do begin 
      Envir := Items[I]; 
      if Envir <> nil then begin 
        if (CompareText(Envir.sMapName, sMapName) = 0) then begin 
          Result := Envir.nServerIndex; 
          break; 
        end; 
      end; 
    end; 
  finally 
    UnLock; 
  end; 
end; 
 
procedure TMapManager.LoadMapDoor; 
var 
  I: Integer; 
begin 
  for I := 0 to Count - 1 do begin 
    TEnvirnoment(Items[I]).AddDoorToMap; 
  end; 
end; 
procedure TMapManager.ProcessMapDoor; 
begin 
 
end; 
 
procedure TMapManager.ReSetMinMap; 
var 
  I, ii: Integer; 
  Envirnoment: TEnvirnoment; 
begin 
  for I := 0 to Count - 1 do begin 
    Envirnoment := TEnvirnoment(Items[I]); 
    if Envirnoment <> nil then begin 
      for ii := 0 to MiniMapList.Count - 1 do begin 
        if CompareText(MiniMapList.Strings[ii], Envirnoment.sMapName) = 0 then begin 
          Envirnoment.nMinMap := Integer(MiniMapList.Objects[ii]); 
          break; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.IsCheapStuff: Boolean; 
begin 
  if m_QuestList.Count > 0 then Result := True 
  else Result := False; 
end; 
 
function TEnvirnoment.AddToMapMineEvent(nX, nY: Integer; nType: Integer; Event: TObject): TObject; 
var 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  bo19, bo1A: Boolean; 
resourcestring 
  sExceptionMsg = '[Exception] TEnvirnoment::AddToMapMineEvent '; 
begin 
  Result := nil; 
  try 
    bo19 := GetMapCellInfo(nX, nY, MapCellInfo); 
    bo1A := False; 
    if bo19 and (MapCellInfo.chFlag <> 0) then begin 
      if (MapCellInfo.ObjList = nil) or (MapCellInfo.boListDisPose) then begin 
        MapCellInfo.ObjList := TList.Create; 
        MapCellInfo.boListDisPose := False; 
      end; 
      if not bo1A then begin 
        New(OSObject); 
        OSObject.btType := nType; 
        OSObject.CellObj := Event; 
        OSObject.dwAddTime := GetTickCount(); 
        OSObject.boObjectDisPose := False; 
        MapCellInfo.ObjList.Add(OSObject); 
        Result := Event; 
      end; 
    end; 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
procedure TEnvirnoment.VerifyMapTime(nX, nY: Integer; BaseObject: TObject); 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  boVerify: Boolean; 
resourcestring 
  sExceptionMsg = '[Exception] TEnvirnoment::VerifyMapTime'; 
begin 
  try 
    boVerify := False; 
    if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo <> nil) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if (OSObject.btType = OS_MOVINGOBJECT) and (OSObject.CellObj = BaseObject) then begin 
            OSObject.dwAddTime := GetTickCount(); 
            boVerify := True; 
            break; 
          end; 
        end; 
      end; 
    end; 
    if not boVerify then 
      AddToMap(nX, nY, OS_MOVINGOBJECT, BaseObject); 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
constructor TEnvirnoment.Create; 
begin 
  Pointer(MapCellArray) := nil; 
  sMapName := ''; 
  sSubMapName := ''; 
  sMainMapName := ''; 
  m_boMainMap := False; 
  nServerIndex := 0; 
  nMinMap := 0; 
  m_nWidth := 0; 
  m_nHeight := 0; 
  m_boDARK := False; 
  m_boDAY := False; 
  m_nMonCount := 0; 
  m_nHumCount := 0; ; 
  m_DoorList := TList.Create; 
  m_QuestList := TList.Create; 
end; 
 
destructor TEnvirnoment.Destroy; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  nX, nY: Integer; 
  DoorInfo: pTDoorInfo; 
begin 
  for nX := 0 to m_nWidth - 1 do begin 
    for nY := 0 to m_nHeight - 1 do begin 
      if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
        for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
          OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
          if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
            if OSObject.CellObj <> nil then begin 
              case OSObject.btType of 
                OS_ITEMOBJECT: DisPose(PTMapItem(OSObject.CellObj)); 
                OS_GATEOBJECT: DisPose(pTGateObj(OSObject.CellObj)); 
                OS_EVENTOBJECT: TEvent(OSObject.CellObj).Free; 
              end; 
            end; 
            DisPose(OSObject); 
          end; 
        end; 
        MapCellInfo.ObjList.Free; 
        MapCellInfo.ObjList := nil; 
      end; 
    end; 
  end; 
 
  for I := 0 to m_DoorList.Count - 1 do begin 
    DoorInfo := m_DoorList.Items[I]; 
    if DoorInfo <> nil then begin 
      Dec(DoorInfo.Status.nRefCount); 
      if DoorInfo.Status.nRefCount <= 0 then 
        DisPose(DoorInfo.Status); 
      DisPose(DoorInfo); 
    end; 
  end; 
  m_DoorList.Free; 
  for I := 0 to m_QuestList.Count - 1 do begin 
    DisPose(pTMapQuestInfo(m_QuestList.Items[I])); 
  end; 
  m_QuestList.Free; 
  FreeMem(MapCellArray); 
  Pointer(MapCellArray) := nil; 
  inherited; 
end; 
 
function TEnvirnoment.LoadMapData(sMapFile: string): Boolean; 
var 
  fHandle: Integer; 
  Header: TMapHeader; 
  nMapSize: Integer; 
  n24, nW, nH: Integer; 
  MapBuffer: pTMap; 
  Point: Integer; 
  Door: pTDoorInfo; 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
begin 
  Result := False; 
  if FileExists(sMapFile) then begin 
    fHandle := FileOpen(sMapFile, fmOpenRead or fmShareExclusive); 
    if fHandle > 0 then begin 
      FileRead(fHandle, Header, SizeOf(TMapHeader)); 
      m_nWidth := Header.wWidth; 
      m_nHeight := Header.wHeight; 
      Initialize(m_nWidth, m_nHeight); 
      nMapSize := m_nWidth * SizeOf(TMapUnitInfo) * m_nHeight; 
 
      MapBuffer := AllocMem(nMapSize); 
      FileRead(fHandle, MapBuffer^, nMapSize); 
 
      for nW := 0 to m_nWidth - 1 do begin 
        n24 := nW * m_nHeight; 
        for nH := 0 to m_nHeight - 1 do begin 
          if (MapBuffer[n24 + nH].wBkImg) and $8000 <> 0 then begin 
            MapCellInfo := @MapCellArray[n24 + nH]; 
            MapCellInfo.chFlag := 1; 
          end; 
          if MapBuffer[n24 + nH].wFrImg and $8000 <> 0 then begin 
            MapCellInfo := @MapCellArray[n24 + nH]; 
            MapCellInfo.chFlag := 2; 
          end; 
          if MapBuffer[n24 + nH].btDoorIndex and $80 <> 0 then begin 
            Point := (MapBuffer[n24 + nH].btDoorIndex and $7F); 
            if Point > 0 then begin 
              New(Door); 
              Door.nX := nW; 
              Door.nY := nH; 
              Door.n08 := Point; 
              Door.Status := nil; 
              for I := 0 to m_DoorList.Count - 1 do begin 
                if abs(pTDoorInfo(m_DoorList.Items[I]).nX - Door.nX) <= 10 then begin 
                  if abs(pTDoorInfo(m_DoorList.Items[I]).nY - Door.nY) <= 10 then begin 
                    if pTDoorInfo(m_DoorList.Items[I]).n08 = Point then begin 
                      Door.Status := pTDoorInfo(m_DoorList.Items[I]).Status; 
                      Inc(Door.Status.nRefCount); 
                      break; 
                    end; 
                  end; 
                end; 
              end; 
              if Door.Status = nil then begin 
                New(Door.Status); 
                Door.Status.boOpened := False; 
                Door.Status.bo01 := False; 
                Door.Status.n04 := 0; 
                Door.Status.dwOpenTick := 0; 
                Door.Status.nRefCount := 1; 
              end; 
              m_DoorList.Add(Door); 
            end; 
          end; 
        end; 
      end; 
      //Dispose(MapBuffer); 
      FreeMem(MapBuffer); 
      FileClose(fHandle); 
      Result := True; 
    end; //004B57B1 
  end; //004B57B1 
end; 
 
procedure TEnvirnoment.Initialize(nWidth, nHeight: Integer); //004B53FC 
var 
  nW, nH: Integer; 
  MapCellInfo: pTMapCellinfo; 
begin 
  if (nWidth > 1) and (nHeight > 1) then begin 
    if MapCellArray <> nil then begin 
      for nW := 0 to m_nWidth - 1 do begin 
        for nH := 0 to m_nHeight - 1 do begin 
          MapCellInfo := @MapCellArray[nW * m_nHeight + nH]; 
          if MapCellInfo.ObjList <> nil then begin 
            MapCellInfo.ObjList.Free; 
            MapCellInfo.ObjList := nil; 
          end; 
        end; 
      end; 
      FreeMem(MapCellArray); 
      Pointer(MapCellArray) := nil; 
    end; //004B54AF 
    m_nWidth := nWidth; 
    m_nHeight := nHeight; 
    Pointer(MapCellArray) := AllocMem((m_nWidth * m_nHeight) * SizeOf(TMapCellinfo)); 
  end; //004B54DB 
end; 
 
//nFlag,boFlag,Monster,Item,Quest,boGrouped 
function TEnvirnoment.CreateQuest(nFlag, nValue: Integer; s24, s28, s2C: string; 
  boGrouped: Boolean): Boolean; //004B6C3C 
var 
  MapQuest: pTMapQuestInfo; 
  MapMerchant: TMerchant; 
begin 
  Result := False; 
  if nFlag < 0 then Exit; 
  New(MapQuest); 
  MapQuest.nFlag := nFlag; 
  if nValue > 1 then nValue := 1; 
  MapQuest.nValue := nValue; 
  if s24 = '*' then s24 := ''; 
  MapQuest.s08 := s24; 
  if s28 = '*' then s28 := ''; 
  MapQuest.s0C := s28; 
  if s2C = '*' then s2C := ''; 
 
  MapQuest.bo10 := boGrouped; 
  MapMerchant := TMerchant.Create; 
  MapMerchant.m_sMapName := '0'; 
  MapMerchant.m_nCurrX := 0; 
  MapMerchant.m_nCurrY := 0; 
  MapMerchant.m_sCharName := s2C; 
  MapMerchant.m_nFlag := 0; 
  MapMerchant.m_wAppr := 0; 
  MapMerchant.m_sFilePath := 'MapQuest_def\'; 
  MapMerchant.m_boIsHide := True; 
  MapMerchant.m_boIsQuest := False; 
 
  UserEngine.QuestNPCList.Add(MapMerchant); 
  MapQuest.NPC := MapMerchant; 
  m_QuestList.Add(MapQuest); 
  Result := True; 
end; 
 
function TEnvirnoment.GetXYObjCount(nX, nY: Integer): Integer; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  Result := 0; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
    for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_MOVINGOBJECT then begin 
          BaseObject := TBaseObject(OSObject.CellObj); 
          if BaseObject <> nil then begin 
            if not BaseObject.m_boGhost and 
              BaseObject.bo2B9 and 
              not BaseObject.m_boDeath and 
              not BaseObject.m_boFixedHideMode and 
              not BaseObject.m_boObMode then begin 
              Inc(Result); 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.GetNextPosition(sX, sY, nDir, nFlag: Integer; var snx: Integer; var sny: Integer): Boolean; 
begin 
  snx := sX; 
  sny := sY; 
  case nDir of 
    DR_UP: if sny > nFlag - 1 then Dec(sny, nFlag); 
    DR_DOWN: if sny < (m_nHeight - nFlag) then Inc(sny, nFlag); 
    DR_LEFT: if snx > nFlag - 1 then Dec(snx, nFlag); 
    DR_RIGHT: if snx < (m_nWidth - nFlag) then Inc(snx, nFlag); 
    DR_UPLEFT: begin 
        if (snx > nFlag - 1) and (sny > nFlag - 1) then begin 
          Dec(snx, nFlag); 
          Dec(sny, nFlag); 
        end; 
      end; 
    DR_UPRIGHT: begin 
        if (snx > nFlag - 1) and (sny < (m_nHeight - nFlag)) then begin 
          Inc(snx, nFlag); 
          Dec(sny, nFlag); 
        end; 
      end; 
    DR_DOWNLEFT: begin 
        if (snx < (m_nWidth - nFlag)) and (sny > nFlag - 1) then begin 
          Dec(snx, nFlag); 
          Inc(sny, nFlag); 
        end; 
      end; 
    DR_DOWNRIGHT: begin 
        if (snx < (m_nWidth - nFlag)) and (sny < (m_nHeight - nFlag)) then begin 
          Inc(snx, nFlag); 
          Inc(sny, nFlag); 
        end; 
      end; 
  end; 
  if (snx = sX) and (sny = sY) then Result := False 
  else Result := True; 
end; 
 
function TEnvirnoment.CanSafeWalk(nX, nY: Integer): Boolean; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
begin 
  Result := True; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (MapCellInfo.ObjList.Count > 0) and (not MapCellInfo.boListDisPose) then begin 
    for I := MapCellInfo.ObjList.Count - 1 downto 0 do begin 
      if MapCellInfo.ObjList.Count <= 0 then break; 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_EVENTOBJECT then begin 
          if TEvent(OSObject.CellObj).m_nDamage > 0 then Result := False; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.ArroundDoorOpened(nX, nY: Integer): Boolean; 
var 
  I: Integer; 
  Door: pTDoorInfo; 
resourcestring 
  sExceptionMsg = '[Exception] TEnvirnoment::ArroundDoorOpened '; 
begin 
  Result := True; 
  try 
    for I := 0 to m_DoorList.Count - 1 do begin 
      Door := m_DoorList.Items[I]; 
      if Door <> nil then begin 
        if (abs(Door.nX - nX) <= 1) and ((abs(Door.nY - nY) <= 1)) then begin 
          if not Door.Status.boOpened then begin 
            Result := False; 
            break; 
          end; 
        end; 
      end; 
    end; 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
function TEnvirnoment.GetMovingObject(nX, nY: Integer; boFlag: Boolean): Pointer; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  Result := nil; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
    for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_MOVINGOBJECT then begin 
          BaseObject := TBaseObject(OSObject.CellObj); 
          if ((BaseObject <> nil) and 
            (not BaseObject.m_boGhost) and 
            (BaseObject.bo2B9)) and 
            ((not boFlag) or (not BaseObject.m_boDeath)) then begin 
            Result := BaseObject; 
            break; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.GetQuestNPC(BaseObject: TObject; sCharName, sStr: string; boFlag: Boolean): TObject; //004B6E4C 
var 
  I: Integer; 
  MapQuestFlag: pTMapQuestInfo; 
  nFlagValue: Integer; 
  bo1D: Boolean; 
begin 
  Result := nil; 
  for I := 0 to m_QuestList.Count - 1 do begin 
    MapQuestFlag := m_QuestList.Items[I]; 
    if MapQuestFlag <> nil then begin 
      nFlagValue := TBaseObject(BaseObject).GetQuestFalgStatus(MapQuestFlag.nFlag); 
      if nFlagValue = MapQuestFlag.nValue then begin 
        if (boFlag = MapQuestFlag.bo10) or (not boFlag) then begin 
          bo1D := False; 
          if (MapQuestFlag.s08 <> '') and (MapQuestFlag.s0C <> '') then begin 
            if (MapQuestFlag.s08 = sCharName) and (MapQuestFlag.s0C = sStr) then 
              bo1D := True; 
          end; 
          if (MapQuestFlag.s08 <> '') and (MapQuestFlag.s0C = '') then begin 
            if (MapQuestFlag.s08 = sCharName) and (sStr = '') then 
              bo1D := True; 
          end; 
          if (MapQuestFlag.s08 = '') and (MapQuestFlag.s0C <> '') then begin 
            if (MapQuestFlag.s0C = sStr) then 
              bo1D := True; 
          end; 
          if bo1D then begin 
            Result := MapQuestFlag.NPC; 
            break; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.GetItemEx(nX, nY: Integer; 
  var nCount: Integer): Pointer; //004B5C10 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  Result := nil; 
  nCount := 0; 
  bo2C := False; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.chFlag = 0) then begin 
    bo2C := True; 
    if (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
      for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
        OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
        if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
          if OSObject.btType = OS_ITEMOBJECT then begin 
            Result := Pointer(OSObject.CellObj); 
            Inc(nCount); 
          end; 
          if OSObject.btType = OS_GATEOBJECT then begin 
            bo2C := False; 
          end; 
          if OSObject.btType = OS_MOVINGOBJECT then begin 
            BaseObject := TBaseObject(OSObject.CellObj); 
            if not BaseObject.m_boDeath then 
              bo2C := False; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.GetDoor(nX, nY: Integer): pTDoorInfo; 
var 
  I: Integer; 
  Door: pTDoorInfo; 
begin 
  Result := nil; 
  for I := 0 to m_DoorList.Count - 1 do begin 
    Door := m_DoorList.Items[I]; 
    if Door <> nil then begin 
      if (Door.nX = nX) and (Door.nY = nY) then begin 
        Result := Door; 
        Exit; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.IsValidObject(nX, nY, nRage: Integer; BaseObject: TObject): Boolean; 
var 
  nXX, nYY, I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
begin 
  Result := False; 
  for nXX := nX - nRage to nX + nRage do begin 
    for nYY := nY - nRage to nY + nRage do begin 
      if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
        for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
          OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
          if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
            if OSObject.CellObj = BaseObject then begin 
              Result := True; 
              Exit; 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.GetRangeBaseObject(nX, nY, nRage: Integer; boFlag: Boolean; 
  BaseObjectList: TList): Integer; 
var 
  nXX, nYY: Integer; 
begin 
  for nXX := nX - nRage to nX + nRage do begin 
    for nYY := nY - nRage to nY + nRage do begin 
      GeTBaseObjects(nXX, nYY, boFlag, BaseObjectList); 
    end; 
  end; 
  if BaseObjectList <> nil then 
    Result := BaseObjectList.Count; 
end; 
//boFlag 是否包括死亡对象 
//FALSE 包括死亡对象 
//TRUE  不包括死亡对象 
function TEnvirnoment.GeTBaseObjects(nX, nY: Integer; boFlag: Boolean; 
  BaseObjectList: TList): Integer; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
    for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_MOVINGOBJECT then begin 
          BaseObject := TBaseObject(OSObject.CellObj); 
          if BaseObject <> nil then begin 
            if not BaseObject.m_boGhost and BaseObject.bo2B9 then begin 
              if not boFlag or not BaseObject.m_boDeath then 
                BaseObjectList.Add(BaseObject); 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
  if BaseObjectList <> nil then 
    Result := BaseObjectList.Count; 
end; 
 
function TEnvirnoment.GetEvent(nX, nY: Integer): TObject; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
begin 
  Result := nil; 
  bo2C := False; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
    for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_EVENTOBJECT then begin 
          Result := OSObject.CellObj; 
        end; 
      end; 
    end; 
  end; 
end; 
 
procedure TEnvirnoment.SetMapXYFlag(nX, nY: Integer; boFlag: Boolean); 
var 
  MapCellInfo: pTMapCellinfo; 
begin 
  if GetMapCellInfo(nX, nY, MapCellInfo) then begin 
    if boFlag and (MapCellInfo <> nil) then MapCellInfo.chFlag := 0 
    else MapCellInfo.chFlag := 2; 
  end; 
end; 
 
function TEnvirnoment.CanFly(nSX, nSY, nDX, nDY: Integer): Boolean; 
var 
  r28, r30: real; 
  n14, n18, n1C: Integer; 
begin 
  Result := True; 
  r28 := (nDX - nSX) / 1.0E1; 
  r30 := (nDY - nDX) / 1.0E1; 
  n14 := 0; 
  while (True) do begin 
    n18 := ROUND(nSX + r28); 
    n1C := ROUND(nSY + r30); 
    if not CanWalk(n18, n1C, True) then begin 
      Result := False; 
      break; 
    end; 
    Inc(n14); 
    if n14 >= 10 then break; 
  end; 
end; 
 
function TEnvirnoment.GetXYHuman(nMapX, nMapY: Integer): Boolean; 
var 
  I: Integer; 
  MapCellInfo: pTMapCellinfo; 
  OSObject: pTOSObject; 
  BaseObject: TBaseObject; 
begin 
  Result := False; 
  if GetMapCellInfo(nMapX, nMapY, MapCellInfo) and (MapCellInfo.ObjList <> nil) and (not MapCellInfo.boListDisPose) then begin 
    for I := 0 to MapCellInfo.ObjList.Count - 1 do begin 
      OSObject := pTOSObject(MapCellInfo.ObjList.Items[I]); 
      if (OSObject <> nil) and (not OSObject.boObjectDisPose) then begin 
        if OSObject.btType = OS_MOVINGOBJECT then begin 
          BaseObject := TBaseObject(OSObject.CellObj); 
          if BaseObject <> nil then begin 
            if BaseObject.m_btRaceServer = RC_PLAYOBJECT then begin 
              Result := True; 
              break; 
            end; 
          end; 
        end; 
      end; 
    end; 
  end; 
end; 
 
function TEnvirnoment.sub_4B5FC8(nX, nY: Integer): Boolean; 
var 
  MapCellInfo: pTMapCellinfo; 
begin 
  Result := True; 
  if GetMapCellInfo(nX, nY, MapCellInfo) and (MapCellInfo <> nil) and (MapCellInfo.chFlag = 2) then 
    Result := False; 
end; 
 
function TEnvirnoment.GetEnvirInfo: string; 
var 
  sMsg: string; 
begin 
  sMsg := '地图名:%s(%s) DAY:%s DARK:%s SAFE:%s FIGHT:%s FIGHT3:%s QUIZ:%s NORECONNECT:%s(%s) MUSIC:%s(%d) EXPRATE:%s(%f) PKWINLEVEL:%s(%d) PKLOSTLEVEL:%s(%d) PKWINEXP:%s(%d) PKLOSTEXP:%s(%d) DECHP:%s(%d/%d) INCHP:%s(%d/%d)'; 
  sMsg := sMsg + ' DECGAMEGOLD:%s(%d/%d) INCGAMEGOLD:%s(%d/%d) INCGAMEPOINT:%s(%d/%d) RUNHUMAN:%s RUNMON:%s NEEDHOLE:%s NORECALL:%s NOGUILDRECALL:%s NODEARRECALL:%s NOMASTERRECALL:%s NODRUG:%s MINE:%s NOPOSITIONMOVE:%s'; 
  Result := format(sMsg, [sMapName, 
    sMapDesc, 
      BoolToCStr(m_boDAY), 
      BoolToCStr(m_boDARK), 
      BoolToCStr(m_boSAFE), 
      BoolToCStr(m_boFightZone), 
      BoolToCStr(m_boFight3Zone), 
      BoolToCStr(m_boQUIZ), 
      BoolToCStr(m_boNORECONNECT), sNoReconnectMap, 
      BoolToCStr(m_boMUSIC), m_nMUSICID, 
      BoolToCStr(m_boEXPRATE), m_nEXPRATE / 100, 
      BoolToCStr(m_boPKWINLEVEL), m_nPKWINLEVEL, 
      BoolToCStr(m_boPKLOSTLEVEL), m_nPKLOSTLEVEL, 
      BoolToCStr(m_boPKWINEXP), m_nPKWINEXP, 
      BoolToCStr(m_boPKLOSTEXP), m_nPKLOSTEXP, 
      BoolToCStr(m_boDECHP), m_nDECHPTIME, m_nDECHPPOINT, 
      BoolToCStr(m_boINCHP), m_nINCHPTIME, m_nINCHPPOINT, 
      BoolToCStr(m_boDecGameGold), m_nDECGAMEGOLDTIME, m_nDecGameGold, 
      BoolToCStr(m_boIncGameGold), m_nINCGAMEGOLDTIME, m_nIncGameGold, 
      BoolToCStr(m_boINCGAMEPOINT), m_nINCGAMEPOINTTIME, m_nINCGAMEPOINT, 
      BoolToCStr(m_boRUNHUMAN), 
      BoolToCStr(m_boRUNMON), 
      BoolToCStr(m_boNEEDHOLE), 
      BoolToCStr(m_boNORECALL), 
      BoolToCStr(m_boNOGUILDRECALL), 
      BoolToCStr(m_boNODEARRECALL), 
      BoolToCStr(m_boNOMASTERRECALL), 
      BoolToCStr(m_boNODRUG), 
      BoolToCStr(m_boMINE), 
      BoolToCStr(m_boNOPOSITIONMOVE) 
      ]); 
end; 
 
procedure TEnvirnoment.AddObject(nType: Integer); 
begin 
  case nType of 
    0: Inc(m_nHumCount); 
    1: Inc(m_nMonCount); 
  end; 
end; 
 
procedure TEnvirnoment.DelObjectCount(BaseObject: TObject); 
var 
  btRaceServer: Byte; 
begin 
  btRaceServer := TBaseObject(BaseObject).m_btRaceServer; 
  if btRaceServer = RC_PLAYOBJECT then Dec(m_nHumCount); 
  if btRaceServer >= RC_ANIMAL then Dec(m_nMonCount); 
end; 
 
procedure TMapManager.Run; 
begin 
 
end; 
 
end.