www.pudn.com > M2Server.rar > DataHandler.pas


//////////////////////////////////////////////////////////////////////////////// 
//                                                                            // 
//                       工程:  M2Server                                     // 
//                       版本:   1.0                                          // 
//                       公司:  乐都在线                                     // 
//                       网址:  http://www.hh8.net                           // 
//                       日期:  2005-05-28                                   // 
//                                                                            // 
//////////////////////////////////////////////////////////////////////////////// 
 
 
unit DataHandler; 
 
interface 
 
uses 
  Windows, Classes, SysUtils, StrUtils, Math, INIFiles, ClassDeclaration, Forms; 
 
//////////////////////////////////////////////////////////////////////////////// 
type 
  TItem = class 
 
  public 
    szName: string[20]; 
    wIndex: LongWord; 
    wStdMode: Word; 
    wShape: Word; 
    wWeight: Word; 
    dwLooks: LongWord; 
    wDuraMax: LongWord; 
    dwRSource: LongWord; 
 
    dwPrice: LongWord; 
 
    m_btType: Byte; 
  public 
    function GetUpgrade(nCount, nRandom: Integer): Integer; 
    procedure GetStandardItem(lpClientItemRcd: PCLIENTITEM_RCD); virtual; 
      abstract; 
    procedure GetUpgradeStdItem(lpClientItemRcd: PCLIENTITEM_RCD; lpUserItemRcd: 
      PUSERITEM_RCD); virtual; abstract; 
  end; 
  tStdItem = class(TItem) 
  public 
    procedure GetStandardItem(lpClientItemRcd: PCLIENTITEM_RCD); override; 
    procedure GetUpgradeStdItem(lpClientItemRcd: PCLIENTITEM_RCD; lpUserItemRcd: 
      PUSERITEM_RCD); override; 
  end; 
  TStdItemSpecial = class(TItem) 
  public 
    btType: Byte; 
    wAniCount: Word; 
    wSource: Word; 
    wAC: Byte; 
    wAC2: Byte; 
    wMAC: Byte; 
    wMAC2: Byte; 
    wDC: Byte; 
    wDC2: Byte; 
    wMC: Byte; 
    wMC2: Byte; 
    wSC: Byte; 
    wSC2: Byte; 
    m_btWater: Byte; 
    m_btWater2: Byte; 
    m_btFire: Byte; 
    m_btFire2: Byte; 
    m_btWind: Byte; 
    m_btWind2: Byte; 
    m_btLight: Byte; 
    m_btLight2: Byte; 
    m_btEarth: Byte; 
    m_btEarth2: Byte; 
    wNeed: Word; 
    wNeedLevel: Word; 
    dwStock: LongWord; 
    dwFeature: LongWord; 
    wReserved: LongWord; 
    public
 procedure ApplyItemParameters(m_pAddAbility: POBJECTADDABILITY_RCD); 
    procedure UpgradeRandomItem(btValue: PChar; var nDura, nDuraMax: Word); 
    procedure GetStandardItem(lpClientItemRcd: PTCLIENTITEM); 
    procedure GetUpgradeStdItem(lpClientItemRcd: PCLIENTITEM_RCD; lpUserItemRcd: 
      PUSERITEM_RCD); override; 
  end; 
  //////////////////////////////////////////////////////////////////////////////// 
  TMagicInfo = class 
 
  public 
    Def: TSTANDARDMAGIC; 
 
  public 
    function GetPower13(nPwr: Integer; nLevel: Integer): Integer; 
    function CheckMagicLevelup(pCharObject: TObject; lptMagicRcd: 
      PHUMANMAGIC_RCD): Boolean; 
 
    function MPow: Integer; 
    function GetSpellPoint(nLevel: Integer): Integer; 
    function GetPower(nPwr, nLevel: Integer): Integer; 
  end; 
 
  //////////////////////////////////////////////////////////////////////////////// 
type 
  TMirMap = class 
 
  public 
    m_stMapFH: TMAPFILEHEADER_RCD; 
 
    m_pMapCellInfo: array of TMAPCELLINFO_RCD; 
 
    m_szMapName: string; 
    m_szMapTextName: string; 
    m_btSeries: Byte; 
    m_btSeriesVal: Byte; 
    m_HumCount: Integer; 
    constructor Create; 
    destructor Destroy; 
 
    function LoadMapData(var pszName: string): Boolean; 
    procedure FreeMapData; 
    function CanMove(nX, nY: Integer; fFlag: Boolean = False): Boolean; 
    function CanSafeWalk(nX, nY: Integer): Boolean; 
 
    function MoveToMovingObject(nX, nY, nTargetX, nTargetY: Integer; 
      pCharObject: TObject): Boolean; 
    function RemoveObject(nX, nY: Integer; btType: Byte; pRemoveObject: 
      Pointer): Boolean; 
    function AddNewObject(nX, nY: Integer; btType: Byte; pAddObject: Pointer): 
      Boolean; 
 
    function GetEvent(nX, nY: Integer): TObject; 
    function GetItem(nX, nY: Integer): PMAPITEM_RCD; 
    function GetObject(nX, nY: Integer): TObject; 
 
    procedure GetMapObject(nX, nY, nArea: Integer; var pList: TThreadList); 
    procedure GetAllObject(nX, nY: Integer; var pList: TThreadList); 
    function GetDupCount(nX, nY: Integer): Integer; 
 
    function GetDropPosition(nOrgX, nOrgY, nRange: Integer; var nX, nY: 
      Integer): Boolean; 
 
    function CheckDoorEvent(nX, nY: Integer; var nEvent: Integer): Integer; 
    function CheckEvent(nX, nY: Integer): Integer; 
 
    function IsValidObject(nX, nY, nCheckRange: Integer; pCharObject: TObject): 
      Boolean; 
    function GetMapCellInfo(nX, nY: Integer): PMAPCELLINFO_RCD; 
  end; 
 
  //////////////////////////////////////////////////////////////////////////////// 
    // function and procedure declaration 
type 
  MAPINFO_RCD_ARRAY = array of TMAPINFO_RCD; 
procedure LoadMap(pMapInfo: PMAPINFO_RCD); 
function GetMap(pszMapName: string): TMirMap; 
 
 
procedure InitMonsterGenInfo; 
procedure InitMagicInfo; 
procedure InitMonRaceInfo; 
function GatMonRaceByName(Name: string): Integer; 
function GetPriceByName(Name: string): Integer; 
procedure InitStdItemSpecial; 
//procedure	InitStdItemEtcInfo; 
procedure	InitMerchantInfo; 
procedure	InitMoveMapEventInfo; 
	function	InitMapInfo(nServerIndex: Integer):	MAPINFO_RCD_ARRAY; 
function GetMagicInfo(nMagicID: Integer): TMagicInfo; 
function GetMonGenInfo(pszMonName: string): PMONSTERGENINFO_RCD; 
function GetMonRaceInfo(pszMonName: string): PMONRACEINFO_RCD; 
implementation
 
uses 
  ObjectEvent, ObjectEngine, PredefinedData, DataManage, GlobalDefinition, 
  MainForm, FunctionDeclaration, MyDebug; 
//************************************************************************************** 
//  Procedure And Functions Declares 
//************************************************************************************** 
{通过物品名称来获取价格} 
function GetPriceByName(Name: string): Integer; 
Var 
  i: integer; 
begin 
  Result := 0; 
  for i := Low(g_pStdItemSpecial) to High(g_pStdItemSpecial) - 1 do 
  begin 
    if g_pStdItemSpecial[i].szName = Name then 
    begin 
      Result := g_pStdItemSpecial[i].dwPrice; 
      Break; 
    end; 
  end; 
end; 
 
 
{登陆地图} 
procedure LoadMap(pMapInfo: PMAPINFO_RCD); 
var 
  szFullName: string; 
  pMirMap: TMirMap; 
begin 
  pMirMap := TMirMap.Create; 
 
  pMirMap.m_btSeries := pMapInfo^.btMapSeries; 
  pMirMap.m_btSeriesVal := pMapInfo^.btMapSeriesValue; 
 
  pMirMap.m_szMapName := pMapInfo^.szMapFileName; 
  pMirMap.m_szMapTextName := pMapInfo^.szMapName; 
 
  szFullName := pMapInfo^.szMapFileName + '.map'; 
  pMirMap.LoadMapData(szFullName); 
end; 
 
{通过地图名获取地图} 
function GetMap(pszMapName: string): TMirMap; 
var 
  I: Integer; 
  pMirMap: TMirMap; 
begin 
  with g_xMirMapList.LockList do 
  begin 
    for I := 0 to COunt - 1 do // Iterate 
    begin 
      pMirMap := TMirMap(items[I]); 
      if (pMirMap.m_szMapName = pszMapName) then 
      begin 
        Result := pMirMap; 
        g_xMirMapList.UnlockList; 
        Exit; 
      end; 
    end; // for 
  end; // with 
  g_xMirMapList.UnlockList; 
  Result := nil; 
end; 
 
{初始化地图信息} 
procedure InitMonsterGenInfo; 
 
var 
  I, j, K: Integer; 
  MonsterGenStrings, temp: Tstrings; 
  MonsterGenStr: string; 
 
begin 
  MonsterGenStrings := TStringList.Create; 
  K := 0; 
  try 
    MonsterGenStrings.LoadFromFile('.\Envir\MonGen.txt'); 
    SetLength(g_pMonGenInfo, MonsterGenStrings.COunt); 
      ///设置g_pmeovmapeventinfo数组的长度,一开始设置得较长; 
 
    for I := 0 to MonsterGenStrings.COunt - 1 do 
    begin 
      MonsterGenStr := Trim(MonsterGenStrings[I]); 
      if Length(MonsterGenStr) <> 0 then /// 
        if MonsterGenStr[1] <> ';' then 
        begin 
          temp := SplitStringByChar(MonsterGenStr, [#1..' ']); 
            //以指定的字符分割字符串 
 
 
          for j := 0 to temp.COunt - 1 do 
          begin 
            case j of 
              0: g_pMonGenInfo[K].szMapName := temp[j]; 
              1: g_pMonGenInfo[K].nX := StrToInt(temp[j]); 
              2: g_pMonGenInfo[K].nY := StrToInt(temp[j]); 
              3: g_pMonGenInfo[K].szMonName := temp[j]; 
              4: g_pMonGenInfo[K].Area := StrToInt(temp[j]); 
              5: g_pMonGenInfo[K].nCount := StrToInt(temp[j]); 
              6: g_pMonGenInfo[K].GenTime := StrToInt(temp[j]); 
              7: g_pMonGenInfo[K].nSmallZenRate := StrToInt(temp[j]); 
            end; 
          end; 
          g_pMonGenInfo[K].nMonIndex := 
            GatMonRaceByName(g_pMonGenInfo[K].szMonName); 
          if g_pMonGenInfo[K].nMonIndex = -1 then 
            Continue; 
          g_pMonGenInfo[K].xMonsterObjList := TThreadList.Create; 
 
          K := K + 1; 
          temp.Free; 
        end; 
 
    end; 
    SetLength(g_pMonGenInfo, K); //重新设置长度,缩短数组的大小 
    g_nNumOfMonGenInfo := K; 
  finally 
    MonsterGenStrings.Free; 
  end; 
end; 
 
{初始化魔法信息} 
procedure InitMagicInfo; 
var 
  I: Integer; 
begin 
  with DataManager.Query1 do 
  begin 
    Close; 
    sql.Clear; 
    sql.Add('SELECT MagID, MagName, EffectType, Effect, Spell, Power, MaxPower, DefSpell, DefPower' + 
      ',DefMaxPower, Job, NeedL1, L1Train, NeedL2, L2Train, NeedL3, L3Train, Delay, Descr FROM "Magic.DB" Magic'); 
    open; 
    first; 
    SetLength(g_pMagicInfo, RecordCount); 
    g_nNumOfMagicInfo := RecordCount; 
    for I := 0 to RecordCount - 1 do 
    begin 
      g_pMagicInfo[I] := TMagicInfo.Create; 
      g_pMagicInfo[I].Def.MagicID := FieldByName('MagID').AsInteger; 
      g_pMagicInfo[I].Def.MagicName := FieldByName('MagName').AsString; 
      g_pMagicInfo[I].Def.EffectType := FieldByName('EffectType').AsInteger; 
      g_pMagicInfo[I].Def.Effect := FieldByName('Effect').AsInteger; 
      g_pMagicInfo[I].Def.spell := FieldByName('Spell').AsInteger; 
      g_pMagicInfo[I].Def.mpower := FieldByName('Power').AsInteger; 
      g_pMagicInfo[I].Def.MaxPower := FieldByName('MaxPower').AsInteger; 
      g_pMagicInfo[I].Def.defspell := FieldByName('DefSpell').AsInteger; 
      g_pMagicInfo[I].Def.MinPower := FieldByName('DefPower').AsInteger; 
      g_pMagicInfo[I].Def.defmaxpower := FieldByName('DefMaxPower').AsInteger; 
      g_pMagicInfo[I].Def.job := FieldByName('Job').AsInteger; 
      g_pMagicInfo[I].Def.Need[0] := FieldByName('NeedL1').AsInteger; 
      g_pMagicInfo[I].Def.Need[1] := FieldByName('NeedL2').AsInteger; 
      g_pMagicInfo[I].Def.Need[2] := FieldByName('NeedL3').AsInteger; 
      g_pMagicInfo[I].Def.MaxTrain[0] := FieldByName('L1Train').AsInteger; 
      g_pMagicInfo[I].Def.MaxTrain[1] := FieldByName('L2Train').AsInteger; 
      g_pMagicInfo[I].Def.MaxTrain[2] := FieldByName('L3Train').AsInteger; 
      g_pMagicInfo[I].Def.Delaytime := FieldByName('Delay').AsInteger; 
      g_pMagicInfo[I].Def.desc := FieldByName('Descr').AsString; 
 
      //showmessage(FieldByName('MagID').AsString ); 
      next; 
    end; 
    Close; 
  end; 
end; 
 
{通过名称获取怪物类型} 
function GatMonRaceByName(Name: string): Integer; 
var 
  I: Integer; 
begin 
  Result := -1; 
  for I := 0 to High(g_pMonRaceInfo) do 
  begin 
    if g_pMonRaceInfo[I].szMonName = Name then 
    begin 
      Result := I; 
      Exit; 
    end; 
 
  end; 
end; 
{初始化类型信息} 
procedure InitMonRaceInfo; 
var 
  I: Integer; 
begin 
  with DataManager.Query1 do 
  begin 
    Close; 
    sql.Clear; 
    sql.Add('SELECT Name, Race, RaceImg, Appr, Lvl, Undead, CoolEye, Exp, HP, MP, AC, MAC,' + 
      ' DC, DCMAX, MC, SC, SPEED, HIT, WALK_SPD, WalkStep, WaLkWait, ATTACK_SPD FROM "Monster.DB" Monster'); 
    open; 
    first; 
    SetLength(g_pMonRaceInfo, RecordCount); 
    g_nNumOfMonRaceInfo := RecordCount; 
    for I := 0 to RecordCount - 1 do 
    begin 
      // g_pMagicInfo[I]             := TMagicInfo.Create; 
      g_pMonRaceInfo[I].nIndex := I; 
      g_pMonRaceInfo[I].szMonName := FieldByName('Name').AsString; 
      g_pMonRaceInfo[I].nMonRace := FieldByName('Race').AsInteger; 
      g_pMonRaceInfo[I].nRaceImg := FieldByName('RaceImg').AsInteger; 
      g_pMonRaceInfo[I].nCoolEye := FieldByName('CoolEye').AsInteger; 
      g_pMonRaceInfo[I].nAppear := FieldByName('Appr').AsInteger; 
      g_pMonRaceInfo[I].btUndead := FieldByName('Undead').AsInteger; 
      g_pMonRaceInfo[I].Level := FieldByName('Lvl').AsInteger; 
      g_pMonRaceInfo[I].HP := FieldByName('HP').AsInteger; 
      g_pMonRaceInfo[I].MP := FieldByName('MP').AsInteger; 
      g_pMonRaceInfo[I].AC := FieldByName('AC').AsInteger; 
      g_pMonRaceInfo[I].MAC := FieldByName('MAC').AsInteger; 
      g_pMonRaceInfo[I].DC := FieldByName('DC').AsInteger; 
      g_pMonRaceInfo[I].MC := FieldByName('MC').AsInteger; 
      g_pMonRaceInfo[I].SC := FieldByName('SC').AsInteger; 
      g_pMonRaceInfo[I].DCMax := FieldByName('DCMAX').AsInteger; 
      g_pMonRaceInfo[I].dwAttackSpeed := FieldByName('ATTACK_SPD').AsInteger; 
      g_pMonRaceInfo[I].WalkWait := FieldByName('WaLkWait').AsInteger; 
      g_pMonRaceInfo[I].WalkStep := FieldByName('WalkStep').AsInteger; 
      g_pMonRaceInfo[I].dwWalkSpeed := FieldByName('WALK_SPD').AsInteger; 
      g_pMonRaceInfo[I].Speed := FieldByName('SPEED').AsInteger; 
      g_pMonRaceInfo[I].Hit := FieldByName('HIT').AsInteger; 
      g_pMonRaceInfo[I].Exp := FieldByName('Exp').AsInteger; 
      g_pMonRaceInfo[I].wRaceIndex := I; 
      next; 
    end; 
    Close; 
  end; 
 
end; 
 
procedure InitStdItemSpecial;             //初始化物品 
var 
  I: Integer; 
begin 
  with DataManager.Query1 do 
  begin 
    Close; 
    sql.Clear; 
    sql.Add('SELECT Idx, Name, Stdmode, Shape, Weight, Anicount, Source, Reserved,' + 
      ' Looks, DuraMax, Ac, Ac2, Mac, Mac2, Dc, Dc2, Mc, Mc2, Sc, Sc2, Need, NeedLevel, Price,' + 
      ' Stock FROM "StdItems.DB" Stditems'); 
    open; 
    first; 
    SetLength(g_pStdItemSpecial, RecordCount); 
    g_nStdItemSpecial := RecordCount; 
    g_pStdItemHash := TStringHash.Create(RecordCount); 
    for I := 0 to RecordCount - 1 do 
    begin 
      g_pStdItemSpecial[I] := TStdItemSpecial.Create; 
      g_pStdItemSpecial[I].wNeed := FieldByName('Need').AsInteger; 
      g_pStdItemSpecial[I].wIndex := FieldByName('Idx').AsInteger; 
      g_pStdItemSpecial[I].wNeedLevel := FieldByName('NeedLevel').AsInteger; 
      g_pStdItemSpecial[I].dwStock := FieldByName('Stock').AsInteger; 
      g_pStdItemSpecial[I].dwLooks := FieldByName('Looks').AsInteger; 
      g_pStdItemSpecial[I].wDuraMax := FieldByName('DuraMax').AsInteger; 
      g_pStdItemSpecial[I].dwPrice := FieldByName('Price').AsInteger; 
      g_pStdItemSpecial[I].wReserved := FieldByName('Reserved').AsInteger; 
      // g_pStdItemSpecial[I]:=FieldByName('').AsInteger; 
      g_pStdItemSpecial[I].szName := FieldByName('Name').AsString; 
      g_pStdItemSpecial[I].wStdMode := FieldByName('Stdmode').AsInteger; 
      g_pStdItemSpecial[I].wShape := FieldByName('Shape').AsInteger; 
      g_pStdItemSpecial[I].wWeight := FieldByName('Weight').AsInteger; 
      g_pStdItemSpecial[I].wAniCount := FieldByName('Anicount').AsInteger; 
      g_pStdItemSpecial[I].wSource := FieldByName('Source').AsInteger; 
      g_pStdItemSpecial[I].wAC := FieldByName('Ac').AsInteger; 
      g_pStdItemSpecial[I].wAC2 := FieldByName('Ac2').AsInteger; 
      g_pStdItemSpecial[I].wMAC := FieldByName('Mac').AsInteger; 
      g_pStdItemSpecial[I].wMAC2 := FieldByName('Mac2').AsInteger; 
      g_pStdItemSpecial[I].wDC := FieldByName('Dc').AsInteger; 
      g_pStdItemSpecial[I].wDC2 := FieldByName('Dc2').AsInteger; 
      g_pStdItemSpecial[I].wMC := FieldByName('Mc').AsInteger; 
      g_pStdItemSpecial[I].wMC2 := FieldByName('Mc2').AsInteger; 
      g_pStdItemSpecial[I].wSC := FieldByName('Sc').AsInteger; 
      g_pStdItemSpecial[I].wSC2 := FieldByName('Sc2').AsInteger; 
      g_pStdItemHash.Add(FieldByName('Name').AsString, I); 
      //g_pMagicInfo[i].nIndex:=FieldByName('MagID').AsInteger; 
      //showmessage(FieldByName('MagID').AsString ); 
      next; 
    end; 
    Close; 
  end; 
end; 
 
{procedure InitStdItemEtcInfo; 
var 
  I:        Integer; 
  szQuery:  TStrings; 
begin 
  szQuery := TStringList.Create; 
 
  szQuery.Clear; 
  szQuery.Add('SELECT COUNT(*) AS FLD_COUNT FROM TBL_STDITEM_ETC'); 
 
  with DataManager.ADOQuerySQL do 
  begin 
    SQL := szQuery; 
    ExecSQL; 
    Open; 
    First; 
    g_nStdItemEtc := StrToInt(FieldByName('FLD_COUNT').AsString); 
    Close; 
  end;    // with 
 
  if g_nStdItemEtc < 0 then 
  begin 
    Exit; 
  end; 
 
  SetLength(g_pStdItemEtc, g_nStdItemEtc); 
 
  szQuery.Clear; 
  szQuery.Add('SELECT * FROM TBL_STDITEM_ETC ORDER BY FLD_INDEX'); 
 
  with DataManager.ADOQuerySQL do 
  begin 
    SQL := szQuery; 
    ExecSQL; 
    Open; 
    First; 
 
    for I := 0 to g_nStdItemEtc - 1 do    // Iterate 
    begin 
      g_pStdItemEtc[I]          := TStdItem.Create; 
      g_pStdItemEtc[I].szName   := FieldByName('FLD_NAME').AsString; 
 
      g_pStdItemEtc[I].wStdMode := StrToInt(FieldByName('FLD_STDMODE').AsString); 
      g_pStdItemEtc[I].wShape   := StrToInt(FieldByName('FLD_SHAPE').AsString); 
      g_pStdItemEtc[I].wWeight  := StrToInt(FieldByName('FLD_WEIGHT').AsString); 
      g_pStdItemEtc[I].dwLooks  := StrToInt(FieldByName('FLD_LOOKS').AsString); 
      g_pStdItemEtc[I].wDuraMax := StrToInt(FieldByName('FLD_VAL1').AsString); 
      g_pStdItemEtc[I].dwRSource:= StrToInt(FieldByName('FLD_VAL2').AsString); 
      g_pStdItemEtc[I].dwPrice  := StrToInt(FieldByName('FLD_PRICE').AsString); 
 
      Next; 
    end;    // for 
 
    Close; 
  end;    // with 
end; 
} 
{初始化商人信息} 
procedure InitMerchantInfo; 
var 
  I, K: Integer; 
  MerChantStrings, temp: Tstrings; 
  MerChantStr: string; 
  Path: string; 
begin 
  MerChantStrings := TStringList.Create; 
  K := 0; 
  try 
    Path := ExtractFilePath(Application.ExeName); 
    if Path[Length(Path)] <> '\' then 
      Path := Path + '\'; 
    MerChantStrings.LoadFromFile('.\Envir\MerChant.txt'); 
    SetLength(g_pMerchantInfo, MerChantStrings.COunt); 
      ///设置g_pmeovmapeventinfo数组的长度,一开始设置得较长; 
 
    for I := 0 to MerChantStrings.COunt - 1 do 
    begin 
      MerChantStr := Trim(MerChantStrings[I]); 
      if Length(MerChantStr) <> 0 then /// 
        if MerChantStr[1] <> ';' then 
        begin 
          temp := SplitStringByChar(MerChantStr, [#1..' ']); 
            //以指定的字符分割字符串 
          if temp.COunt < 8 then 
            Continue; 
 
          g_pMerchantInfo[K].idStr := temp[0]; 
          g_pMerchantInfo[K].szMapName := temp[1]; 
          g_pMerchantInfo[K].nPosX := StrToInt(temp[2]); 
          g_pMerchantInfo[K].nPosY := StrToInt(temp[3]); 
          g_pMerchantInfo[K].szNPCName := temp[4]; 
          g_pMerchantInfo[K].sFace := StrToInt(temp[5]); 
          g_pMerchantInfo[K].sBody := StrToInt(temp[6]); 
          g_pMerchantInfo[K].sGender := StrToInt(temp[7]); 
          Inc(K); 
          temp.Free; 
        end; 
 
    end; 
    SetLength(g_pMerchantInfo, K); //重新设置长度,缩短数组的大小 
    g_nNumOfMerchantInfo := K; 
  finally 
    MerChantStrings.Free; 
  end; 
end; 
 
{} 
procedure InitMoveMapEventInfo; ///初始化移动地图事件信息 
var 
  I, K, flag: Integer; 
  MapInfoStrings, temp: Tstrings; 
  MapInfoStr: string; 
begin 
  MapInfoStrings := TStringList.Create; 
  K := 0; 
  try 
    MapInfoStrings.LoadFromFile('.\Envir\MapInfo.txt'); 
    SetLength(g_pMoveMapEventInfo, MapInfoStrings.COunt); 
      ///设置g_pmeovmapeventinfo数组的长度,一开始设置得较长; 
 
    for I := 0 to MapInfoStrings.COunt - 1 do 
    begin 
      MapInfoStr := Trim(MapInfoStrings[I]); 
      if Length(MapInfoStr) <> 0 then /// 
        if MapInfoStr[1] <> ';' then 
        begin 
          flag := pos('->', MapInfoStr); 
          if flag > 0 then 
          begin 
            Insert(' ', MapInfoStr, flag); 
            Insert(' ', MapInfoStr, flag + 3); 
            temp := SplitStringByChar(MapInfoStr, [#1..' ', ',', ':', '.']); 
            g_pMoveMapEventInfo[K].szSMapFileName := temp[0]; 
            g_pMoveMapEventInfo[K].szDMapFileName := temp[4]; 
            g_pMoveMapEventInfo[K].nSX := StrToInt(temp[1]); 
            g_pMoveMapEventInfo[K].nSY := StrToInt(temp[2]); 
            g_pMoveMapEventInfo[K].nDX := StrToInt(temp[5]); 
            g_pMoveMapEventInfo[K].nDY := StrToInt(temp[6]); 
            g_pMoveMapEventInfo[K].fIsOpen := False; 
            K := K + 1; 
            temp.Free; 
          end; 
        end; 
    end; 
    SetLength(g_pMoveMapEventInfo, K); 
    g_nNumOfMoveMapEventInfo := K; 
  finally 
    MapInfoStrings.Free; 
  end; 
end; 
 
{初始化地图,并返回地图的信息} 
function InitMapInfo(nServerIndex: Integer): MAPINFO_RCD_ARRAY; //初始化地图信息; 
var 
  MapInfoStrings, tempStrings: Tstrings; 
  MapInfoStr: string; 
  Attribute: string; 
  I, K, flag, tempflag: Integer; 
  pMapInfo: MAPINFO_RCD_ARRAY; 
begin 
  MapInfoStrings := TStringList.Create; 
  K := 0; 
  try 
    MapInfoStrings.LoadFromFile('.\Envir\mapinfo.txt'); 
    SetLength(pMapInfo, MapInfoStrings.COunt); 
    for I := 0 to MapInfoStrings.COunt - 1 do 
    begin 
      MapInfoStr := Trim(MapInfoStrings[I]); 
      if Length(MapInfoStr) <> 0 then 
        if MapInfoStr[1] <> ';' then 
        begin 
          flag := pos(']', MapInfoStr); 
          if flag <> 0 then 
          begin 
            tempflag := pos('[', MapInfoStr); 
            tempStrings := SplitStringByChar(Copy(MapInfoStr, tempflag + 1, flag 
              - tempflag - 1), [#1..' ']); 
            Attribute := Trim(midbstr(MapInfoStr, flag + 1, 
              Length(MapInfoStr))); 
            //if nServerIndex=strtoint(tempStrings[2]) then 
            begin 
              pMapInfo[K].szMapFileName := tempStrings[0]; 
              pMapInfo[K].szMapName := tempStrings[1]; 
              pMapInfo[K].Attribute := Attribute; 
              K := K + 1; 
            end; 
            tempStrings.Free; 
          end; 
        end; 
    end; 
    SetLength(pMapInfo, K); 
    g_nNumOfMapInfo := K; 
    Result := pMapInfo; 
  finally 
    MapInfoStrings.Free; 
  end; 
end; 
 
{通过魔法ID获取魔法信息} 
function GetMagicInfo(nMagicID: Integer): TMagicInfo; 
var 
  I: Integer; 
begin 
  if g_pMagicInfo[nMagicID].Def.MagicID = nMagicID then 
  begin 
    Result := g_pMagicInfo[nMagicID]; 
    Exit; 
  end; 
 
  for I := 0 to g_nNumOfMagicInfo - 1 do 
  begin 
    if g_pMagicInfo[I].Def.MagicID = nMagicID then 
    begin 
      Result := g_pMagicInfo[I]; 
      Exit; 
    end; 
  end; 
 
  Result := nil; 
end; 
 
{} 
function GetMonGenInfo(pszMonName: string): PMONSTERGENINFO_RCD; 
var 
  I, 
    nCmpLen, 
    nLen: Integer; 
begin 
  nLen := StrLen(PChar(pszMonName)); 
  for I := 0 to g_nNumOfMonGenInfo - 1 do // Iterate 
  begin 
    nCmpLen := StrLen(@g_pMonGenInfo[I].szMonName[1]); 
 
    if nCmpLen = nLen then 
    begin 
      if LeftBStr(g_pMonGenInfo[I].szMonName, 
        StrLen(@g_pMonGenInfo[I].szMonName[1])) = LeftBStr(pszMonName, 
        StrLen(@pszMonName[1])) then 
      begin 
        Result := @g_pMonGenInfo[I]; 
      end; 
    end; 
  end; // for 
 
  Result := nil; 
end; 
 
function GetMonRaceInfo(pszMonName: string): PMONRACEINFO_RCD; 
var 
  I, 
    nCmpLen, 
    nLen: Integer; 
begin 
  Result := nil; 
  nLen := StrLen(PChar(pszMonName)); 
  for I := 0 to g_nNumOfMonRaceInfo - 1 do // Iterate 
  begin 
    nCmpLen := StrLen(@g_pMonRaceInfo[I].szMonName[1]); 
 
    if nCmpLen = nLen then 
    begin 
      if g_pMonRaceInfo[I].szMonName = pszMonName then 
      begin 
        Result := @g_pMonRaceInfo[I]; 
        Break; 
      end; 
    end; 
  end; // for 
 
 
end; 
 
//************************************************************************************** 
//  TItem Class Members 
//************************************************************************************** 
{} 
function TItem.GetUpgrade(nCount, nRandom: Integer): Integer; 
var 
  I, 
    nResult: Integer; 
begin 
  nResult := 0; 
 
  for I := 0 to nCount - 1 do 
  begin 
    if (Random(32767) mod nRandom) = 0 then 
    begin 
      Inc(nResult); 
    end 
    else 
    begin 
      Break; 
    end; 
  end; 
 
  Result := nResult; 
end; 
 
//************************************************************************************** 
//  TStdItem Class Members 
//************************************************************************************** 
procedure tStdItem.GetStandardItem(lpClientItemRcd: PCLIENTITEM_RCD); 
begin 
  CopyMemory(@lpClientItemRcd^.tStdItem.szName[1], @szName[1], 20); 
  lpClientItemRcd^.tStdItem.btStdMode := Byte(wStdMode); 
  lpClientItemRcd^.tStdItem.btShape := Byte(wShape); 
  lpClientItemRcd^.tStdItem.btWeight := Byte(wWeight); 
  lpClientItemRcd^.tStdItem.btAniCount := 0; 
  lpClientItemRcd^.tStdItem.btSource := 0; 
  lpClientItemRcd^.tStdItem.wLooks := Word(dwLooks); 
  lpClientItemRcd^.tStdItem.wDuraMax := Word(wDuraMax); 
  lpClientItemRcd^.tStdItem.btNeed := 0; 
  lpClientItemRcd^.tStdItem.btNeedLevel := 0; 
  lpClientItemRcd^.tStdItem.nPrice := dwPrice; 
end; 
 
procedure tStdItem.GetUpgradeStdItem(lpClientItemRcd: PCLIENTITEM_RCD; 
  lpUserItemRcd: PUSERITEM_RCD); 
begin 
  // Do nothing Now 
end; 
 
//************************************************************************************** 
//  TStdItemSpecial Class Members 
//************************************************************************************** 
procedure TStdItemSpecial.GetStandardItem(lpClientItemRcd: PTCLIENTITEM); 
begin 
  lpClientItemRcd.s.Name := szName; 
  lpClientItemRcd^.s.StdMode := Byte(wStdMode); 
  lpClientItemRcd^.s.Shape := Byte(wShape); 
  lpClientItemRcd^.s.Weight := Byte(wWeight); 
  lpClientItemRcd^.s.AniCount := Byte(wAniCount); 
  lpClientItemRcd^.s.source := Byte(wSource); 
  lpClientItemRcd^.s.Looks := Word(dwLooks); 
  lpClientItemRcd^.s.DuraMax := Word(wDuraMax); 
  lpClientItemRcd^.s.Need := Byte(wNeed); 
  lpClientItemRcd^.s.NeedLevel := Byte(wNeedLevel); 
  lpClientItemRcd^.s.Price := dwPrice; 
  lpClientItemRcd^.s.AC := MAKEWORD(wAC, wAC2); 
  lpClientItemRcd^.s.MAC := MAKEWORD(wMAC, wMAC2); 
  lpClientItemRcd^.s.DC := MAKEWORD(wDC, wDC2); 
  lpClientItemRcd^.s.MC := MAKEWORD(wMC, wMC2); 
  lpClientItemRcd^.s.SC := MAKEWORD(wSC, wSC2); 
  lpClientItemRcd^.s.bNeed := wNeed; 
  lpClientItemRcd^.s.NeedIdentify := wReserved; 
  lpClientItemRcd^.s.SpecialPower := wReserved; 
  lpClientItemRcd.Dura := wDuraMax; 
  lpClientItemRcd.DuraMax := wDuraMax; 
end; 
 
procedure TStdItemSpecial.GetUpgradeStdItem(lpClientItemRcd: PCLIENTITEM_RCD; 
  lpUserItemRcd: PUSERITEM_RCD); 
begin 
  case btType of // 
    0: 
      begin 
        lpClientItemRcd^.tStdItem.wDC := MAKEWORD(wDC, wDC2 + 
          lpUserItemRcd^.btValue[0]); 
        lpClientItemRcd^.tStdItem.wMC := MAKEWORD(wMC, wMC2 + 
          lpUserItemRcd^.btValue[1]); 
        lpClientItemRcd^.tStdItem.wSC := MAKEWORD(wSC, wSC2 + 
          lpUserItemRcd^.btValue[2]); 
        lpClientItemRcd^.tStdItem.wAC := MAKEWORD(wAC + 
          lpUserItemRcd^.btValue[3], wAC2 + lpUserItemRcd^.btValue[5]); 
        lpClientItemRcd^.tStdItem.wMAC := MAKEWORD(wMAC + 
          lpUserItemRcd^.btValue[4], wMAC2 + lpUserItemRcd^.btValue[6]); 
        lpClientItemRcd^.tStdItem.btSource := lpUserItemRcd^.btValue[7]; 
      end; 
    1: 
      begin 
        lpClientItemRcd^.tStdItem.wAC := MAKEWORD(wAC, wAC2 + 
          lpUserItemRcd^.btValue[0]); 
        lpClientItemRcd^.tStdItem.wMAC := MAKEWORD(wMAC, wMAC2 + 
          lpUserItemRcd^.btValue[1]); 
        lpClientItemRcd^.tStdItem.wDC := MAKEWORD(wDC, wDC2 + 
          lpUserItemRcd^.btValue[2]); 
        lpClientItemRcd^.tStdItem.wMC := MAKEWORD(wMC, wMC2 + 
          lpUserItemRcd^.btValue[3]); 
        lpClientItemRcd^.tStdItem.wSC := MAKEWORD(wSC, wSC2 + 
          lpUserItemRcd^.btValue[4]); 
      end; 
    2: 
      begin 
        lpClientItemRcd^.tStdItem.wAC := MAKEWORD(wAC, wAC2 + 
          lpUserItemRcd^.btValue[0]); 
        lpClientItemRcd^.tStdItem.wMAC := MAKEWORD(wMAC, wMAC2 + 
          lpUserItemRcd^.btValue[1]); 
        lpClientItemRcd^.tStdItem.wDC := MAKEWORD(wDC, wDC2 + 
          lpUserItemRcd^.btValue[2]); 
        lpClientItemRcd^.tStdItem.wMC := MAKEWORD(wMC, wMC2 + 
          lpUserItemRcd^.btValue[3]); 
        lpClientItemRcd^.tStdItem.wSC := MAKEWORD(wSC, wSC2 + 
          lpUserItemRcd^.btValue[4]); 
      end; 
  else 
    begin 
      lpClientItemRcd^.tStdItem.wAC := 0; 
      lpClientItemRcd^.tStdItem.wMAC := 0; 
      lpClientItemRcd^.tStdItem.wDC := 0; 
      lpClientItemRcd^.tStdItem.wMC := 0; 
      lpClientItemRcd^.tStdItem.wSC := 0; 
      lpClientItemRcd^.tStdItem.btSource := 0; 
    end; 
  end; //case 
end; 
 
procedure TStdItemSpecial.UpgradeRandomItem(btValue: PChar; var nDura, nDuraMax: 
  Word); 
var 
  nUpgrade, 
    nIncp, 
    nVal: Integer; 
begin 
  case btType of // 
    0: 
      begin 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 15) = 0 then 
        begin 
          btValue[0] := Char(1 + nUpgrade); // DC 
        end; 
 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 20) = 0 then 
        begin 
          nIncp := (1 + nUpgrade) div 3; 
 
          if nIncp > 0 then 
          begin 
            if (Random(32767) mod 3) <> 0 then 
            begin 
              btValue[6] := Char(nIncp); 
            end 
            else 
            begin 
              btValue[6] := Char(10 + nIncp); 
            end; 
          end; 
        end; 
 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 15) = 0 then 
        begin 
          btValue[1] := Char(1 + nUpgrade); // MC 
        end; 
 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 15) = 0 then 
        begin 
          btValue[2] := Char(1 + nUpgrade); // SC 
        end; 
 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 24) = 0 then 
        begin 
          btValue[5] := Char(1 + nUpgrade div 2); 
        end; 
 
        nUpgrade := GetUpgrade(12, 12); 
        if (Random(32767) mod 3) < 2 then 
        begin 
          nVal := (1 + nUpgrade) * 2000; 
 
          nDuraMax := Min(65000, nDuraMax + nVal); 
          nDura := Min(65000, nDura + nVal); 
        end; 
 
        nUpgrade := GetUpgrade(12, 15); 
        if (Random(32767) mod 10) = 0 then 
        begin 
          btValue[7] := Char(1 + nUpgrade div 2); 
        end; 
      end; 
    1: 
      begin 
        nUpgrade := GetUpgrade(6, 15); 
        if (Random(32767) mod 40) = 0 then 
        begin 
          btValue[0] := Char(1 + nUpgrade); // AC 
        end; 
 
        nUpgrade := GetUpgrade(6, 15); 
        if (Random(32767) mod 40) = 0 then 
        begin 
          btValue[1] := Char(1 + nUpgrade); // MAC 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 40) = 0 then 
        begin 
          btValue[2] := Char(1 + nUpgrade); // DC 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 40) = 0 then 
        begin 
          btValue[3] := Char(1 + nUpgrade); // MC 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 40) = 0 then 
        begin 
          btValue[4] := Char(1 + nUpgrade); // SC 
        end; 
 
        nUpgrade := GetUpgrade(6, 10); 
        if (Random(32767) mod 8) < 6 then 
        begin 
          nVal := (1 + nUpgrade) * 2000; 
 
          nDuraMax := Min(65000, nDuraMax + nVal); 
          nDura := Min(65000, nDura + nVal); 
        end; 
      end; 
    2: 
      begin 
        nUpgrade := GetUpgrade(6, 30); 
        if (Random(32767) mod 60) = 0 then 
        begin 
          btValue[0] := Char(1 + nUpgrade); // AC(HIT) 
        end; 
 
        nUpgrade := GetUpgrade(6, 30); 
        if (Random(32767) mod 60) = 0 then 
        begin 
          btValue[1] := Char(1 + nUpgrade); // MAC(SPEED) 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 30) = 0 then 
        begin 
          btValue[2] := Char(1 + nUpgrade); // DC 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 30) = 0 then 
        begin 
          btValue[3] := Char(1 + nUpgrade); // MC 
        end; 
 
        nUpgrade := GetUpgrade(6, 20); 
        if (Random(32767) mod 30) = 0 then 
        begin 
          btValue[4] := Char(1 + nUpgrade); // SC 
        end; 
 
        nUpgrade := GetUpgrade(6, 12); 
        if (Random(32767) mod 20) < 15 then 
        begin 
          nVal := (1 + nUpgrade) * 1000; 
 
          nDuraMax := Min(65000, nDuraMax + nVal); //DURA Stuffs 
          nDura := Min(65000, nDura + nVal); 
        end; 
      end; 
  end; //case 
end; 
 
procedure TStdItemSpecial.ApplyItemParameters(m_pAddAbility: 
  POBJECTADDABILITY_RCD); 
begin 
  case btType of // 
    0: 
      begin 
        m_pAddAbility^.Hit := m_pAddAbility^.Hit + wAC2; 
 
        if wMAC2 > 10 then 
        begin 
          m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed + wMAC2 - 10; 
        end 
        else 
        begin 
          m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed - wMAC2; 
        end; 
 
        m_pAddAbility^.Luck := m_pAddAbility^.Luck + wAC; 
        m_pAddAbility^.UnLuck := m_pAddAbility^.UnLuck + wMAC; 
      end; 
    1: 
      begin 
        m_pAddAbility^.AC := MAKEWORD(LOBYTE(m_pAddAbility^.AC) + wAC, 
          HIBYTE(m_pAddAbility^.AC) + wAC2); 
        m_pAddAbility^.MAC := MAKEWORD(LOBYTE(m_pAddAbility^.MAC) + wMAC, 
          HIBYTE(m_pAddAbility^.MAC) + wMAC2); 
      end; 
    2: 
      begin 
        case wStdMode of 
          21: 
            begin 
              m_pAddAbility^.AntiMagic := m_pAddAbility^.AntiMagic + wAC2; 
              m_pAddAbility^.UnLuck := m_pAddAbility^.UnLuck + wMAC; 
              m_pAddAbility^.Luck := m_pAddAbility^.Luck + wMAC2; 
            end; 
          22, 
            41: 
            begin 
              m_pAddAbility^.Hit := m_pAddAbility^.Hit + wAC2; 
              m_pAddAbility^.Speed := m_pAddAbility^.Speed + wMAC2; 
            end; 
          23: 
            begin 
              m_pAddAbility^.HealthRecover := m_pAddAbility^.HealthRecover + 
                wAC2; 
              m_pAddAbility^.SpellRecover := m_pAddAbility^.SpellRecover + 
                wMAC2; 
              m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed + wAC; 
              m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed - wMAC; 
            end; 
          32: 
            begin 
              m_pAddAbility^.AntiPoison := m_pAddAbility^.AntiPoison + wAC2; 
              m_pAddAbility^.PoisonRecover := m_pAddAbility^.PoisonRecover + 
                wMAC2; 
              m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed + wAC; 
              m_pAddAbility^.HitSpeed := m_pAddAbility^.HitSpeed - wMAC; 
            end; 
        else 
          begin 
            m_pAddAbility^.AC := MAKEWORD(LOBYTE(m_pAddAbility^.AC) + wAC, 
              HIBYTE(m_pAddAbility^.AC) + wAC2); 
            m_pAddAbility^.MAC := MAKEWORD(LOBYTE(m_pAddAbility^.MAC) + wMAC, 
              HIBYTE(m_pAddAbility^.MAC) + wMAC2); 
          end; 
        end; 
      end; 
  end; // case 
 
  m_pAddAbility^.DC := wDC + wDC2; 
  m_pAddAbility^.MC := wMC + wMC2; 
  m_pAddAbility^.SC := wSC + wSC2; 
end; 
 
//************************************************************************************** 
//  TMagicInfo Class Members 
//************************************************************************************** 
function TMagicInfo.GetPower13(nPwr: Integer; nLevel: Integer): Integer; 
var 
  p1, 
    p2: Single; 
begin 
  p1 := nPwr / 3; 
  p2 := nPwr - p1; 
  with Def do 
  begin 
    if (defmaxpower - MinPower) > 0 then 
    begin 
      Result := Round(p1 + p2 / 4 * (nLevel + 1) + MinPower + (Random(32767) mod 
        (defmaxpower - MinPower))); 
      Exit; 
    end 
    else 
    begin 
      Result := Round(p1 + p2 / 4 * (nLevel + 1) + MinPower); 
      Exit; 
    end; 
  end; 
end; 
 
function TMagicInfo.CheckMagicLevelup(pCharObject: TObject; lptMagicRcd: 
  PHUMANMAGIC_RCD): Boolean;              //提升魔法等级? 
var 
  nLevel: Integer; 
begin 
  if (Integer(lptMagicRcd^.btLevel) >= 0) and (Integer(lptMagicRcd^.btLevel) <= 
    3) then 
  begin 
    nLevel := Integer(lptMagicRcd^.btLevel); 
  end 
  else 
  begin 
    nLevel := 0; 
  end; 
 
  if Integer(lptMagicRcd^.btLevel) < 3 then 
  begin 
    if lptMagicRcd^.nCurrTrain >= Def.MaxTrain[nLevel] then 
    begin 
      if Integer(lptMagicRcd^.btLevel) < 3 then 
      begin 
        lptMagicRcd^.nCurrTrain := lptMagicRcd^.nCurrTrain - 
          Def.MaxTrain[nLevel]; 
        lptMagicRcd^.btLevel := Char(Integer(lptMagicRcd^.btLevel) + 1); 
 
        TCharObject(pCharObject).UpdateDelayProcessCheckParam1(TCharObject(pCharObject), 
          RM_MAGIC_LVEXP, 0, lptMagicRcd^.nCurrTrain, 
          Integer(lptMagicRcd^.btLevel), 
          lptMagicRcd^.btMagicID, '', 800); 
      end 
      else 
      begin 
        lptMagicRcd^.nCurrTrain := Def.MaxTrain[nLevel]; 
      end; 
 
      Result := True; 
      Exit; 
    end; 
  end; 
 
  Result := False; 
end; 
 
function TMagicInfo.MPow: Integer; 
begin 
  if (Def.defmaxpower - Def.MinPower) > 0 then 
  begin 
    Result := Def.MinPower + (Random(32767) mod (Def.defmaxpower - 
      Def.MinPower)); 
  end 
  else 
  begin 
    Result := Def.MinPower; 
  end; 
end; 
 
function TMagicInfo.GetSpellPoint(nLevel: Integer): Integer; 
begin 
  Result := Round(Def.spell / 4 * (nLevel + 1)) + Def.defspell; 
end; 
 
function TMagicInfo.GetPower(nPwr, nLevel: Integer): Integer; 
begin 
  if (Def.defmaxpower - Def.MinPower) > 0 then 
  begin 
    Result := Round(nPwr / 4 * (nLevel + 1)) + Def.MinPower + (Random(32767) mod 
      (Def.defmaxpower - Def.MinPower)); 
  end 
  else 
  begin 
    Result := Round(nPwr / 4 * (nLevel + 1)) + Def.MinPower; 
  end; 
end; 
 
//************************************************************************************** 
//  TMirMap Class Members 
//************************************************************************************** 
constructor TMirMap.Create; 
begin 
  m_HumCount := 0; 
  m_pMapCellInfo := nil; 
end; 
 
destructor TMirMap.Destroy; 
begin 
  FreeMapData; 
end; 
 
function TMirMap.IsValidObject(nX, nY, nCheckRange: Integer; pCharObject: 
  TObject): Boolean; 
var 
  I: Integer; 
  iX, iY: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
begin 
  for iX := nX - nCheckRange to nX + nCheckRange do // Iterate 
  begin 
    for iY := nY - nCheckRange to nY + nCheckRange do // Iterate 
    begin 
      pMapCellInfo := GetMapCellInfo(iX, iY); 
      if pMapCellInfo <> nil then 
      begin 
        with pMapCellInfo^.m_xpObjectList.LockList do 
        begin 
          for I := 0 to COunt - 1 do // Iterate 
          begin 
            pOSObject := POSOBJECT_RCD(items[I]); 
            if pOSObject^.btType = OS_MOVINGOBJECT then 
            begin 
              pCharObject := TCharObject(pOSObject^.pObject); 
              if pCharObject <> nil then 
              begin 
                Result := True; 
                pMapCellInfo^.m_xpObjectList.UnlockList; 
                Exit; 
              end; 
            end; 
          end; // for 
        end; // with 
        pMapCellInfo^.m_xpObjectList.UnlockList; 
      end; 
    end; // for 
  end; // for 
  Result := False; 
end; 
 
function TMirMap.LoadMapData(var pszName: string): Boolean; 
var 
  I: Integer; 
  hofFile: Integer; 
  dwReadLen: LongWord; 
  nMapSize: Integer; 
  pstCellInfo: array of TCELLINFO_RCD; 
  szMapFileName, 
    szPath: string; 
begin 
  szMapFileName := g_IniConfiguration.MapFileLoc + '\' + pszName; 
  hofFile := FileOpen(szMapFileName, fmOpenRead or fmShareDenyNone); 
  if hofFile <> 0 then 
  begin 
    FreeMapData; 
    FileRead(hofFile, PChar(@m_stMapFH)^, SizeOf(TMAPFILEHEADER_RCD)); 
 
    nMapSize := m_stMapFH.shWidth * m_stMapFH.shHeight; 
 
    //    FileSeek(hofFile, sizeof(TTILEINFO_RCD)*(nMapSize shr 2), 1); 
 
    SetLength(pstCellInfo, nMapSize); 
    FileRead(hofFile, PChar(pstCellInfo)^, SizeOf(TCELLINFO_RCD) * nMapSize); 
    FileClose(hofFile); 
 
    SetLength(m_pMapCellInfo, nMapSize); 
 
    for I := 0 to nMapSize - 1 do // Iterate 
    begin 
      if ((pstCellInfo[I].BkImg and $8000) + (pstCellInfo[I].FrImg and $8000)) > 
        0 then 
        m_pMapCellInfo[I].CanMove := 1 
      else 
        m_pMapCellInfo[I].CanMove := 0; 
 
      m_pMapCellInfo[I].m_chFlag := pstCellInfo[I].DoorIndex; 
      m_pMapCellInfo[I].m_sLightNEvent := pstCellInfo[I].light; 
      m_pMapCellInfo[I].m_xpObjectList := nil; 
    end; // for 
 
    pstCellInfo := nil; 
    g_xMirMapList.Add(self); 
 
    Result := True; 
    Exit; 
  end; 
  Result := False; 
end; 
 
procedure TMirMap.FreeMapData; 
var 
  nMapSize: Integer; 
  I: Integer; 
begin 
  if m_pMapCellInfo <> nil then 
  begin 
    nMapSize := m_stMapFH.shWidth * m_stMapFH.shHeight; 
    for I := 0 to nMapSize - 1 do // Iterate 
    begin 
      m_pMapCellInfo[I].m_xpObjectList.Clear; 
      m_pMapCellInfo[I].m_xpObjectList := nil; 
    end; // for 
  end; 
  m_pMapCellInfo := nil; 
end; 
 
function TMirMap.CanMove(nX, nY: Integer; fFlag: Boolean): Boolean; 
var 
  I: Integer; 
  fRet: Boolean; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pCharObject: TCharObject; 
  pOSObject: POSOBJECT_RCD; 
begin 
  fRet := False; 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
  if pMapCellInfo = nil then 
  begin 
    Result := False; 
    Exit; 
  end; 
  if pMapCellInfo.CanMove > 0 then 
  begin 
    Result := False; 
    Exit; 
  end; 
 
  if pMapCellInfo <> nil then 
  begin 
    fRet := True; 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := POSOBJECT_RCD(items[I]); 
          if pOSObject^.btType = OS_MOVINGOBJECT then 
          begin 
            pCharObject := TCharObject(pOSObject^.pObject); 
            if (pCharObject.m_fIsDead = False) and (pCharObject.m_fInspector = 
              False) and (pCharObject.m_fHideMode = False) then 
            begin 
              if fFlag = False then 
              begin 
                fRet := False; 
                Break; 
              end; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := fRet; 
end; 
 
function TMirMap.CheckDoorEvent(nX, nY: Integer; var nEvent: Integer): Integer; 
var 
  pMapCellInfo: PMAPCELLINFO_RCD; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
    if (pMapCellInfo^.m_sLightNEvent and $2) > 0 then // Door Event 
    begin 
      nEvent := (pMapCellInfo^.m_sLightNEvent and $3FFF) shr 4; 
      if (pMapCellInfo^.m_sLightNEvent and $8) > 0 then // Event 
      begin 
        if (pMapCellInfo^.m_sLightNEvent and $C000) > 0 then 
        begin 
          Result := _DOOR_MAPMOVE_BACK; 
          Exit; 
        end 
        else 
        begin 
          Result := _DOOR_MAPMOVE_FRONT; 
          Exit; 
        end; 
      end; 
      Result := _DOOR_OPEN; 
      Exit; 
    end; 
  end; 
  Result := _DOOR_NOT; 
end; 
 
function TMirMap.CheckEvent(nX, nY: Integer): Integer; 
var 
  pMapCellInfo: PMAPCELLINFO_RCD; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
    if (pMapCellInfo^.m_sLightNEvent and $4) > 0 then // Event 
    begin 
      Result := (pMapCellInfo^.m_sLightNEvent and $C000) shr 4; 
      Exit; 
    end; 
  end; 
  Result := 0; 
end; 
 
function TMirMap.MoveToMovingObject(nX, nY, nTargetX, nTargetY: Integer; 
  pCharObject: TObject): Boolean; 
var 
  fRet: Boolean; 
begin 
  fRet := False; 
 
  if RemoveObject(nX, nY, OS_MOVINGOBJECT, pCharObject) then 
  begin 
    if AddNewObject(nTargetX, nTargetY, OS_MOVINGOBJECT, pCharObject) then 
      fRet := True 
    else 
      fRet := False; 
  end 
  else 
    fRet := False; 
 
  Result := fRet; 
end; 
 
function TMirMap.RemoveObject(nX, nY: Integer; btType: Byte; pRemoveObject: 
  Pointer): Boolean; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
  pCharObject: TCharObject; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
 
    if pMapCellInfo^.m_xpObjectList = nil then 
    begin 
      Result := False; 
      Exit; 
    end; 
 
    with pMapCellInfo^.m_xpObjectList.LockList do 
    begin 
      for I := 0 to COunt - 1 do // Iterate 
      begin 
        pOSObject := POSOBJECT_RCD(items[I]); 
        if pOSObject <> nil then 
        begin 
          if (pOSObject^.pObject = pRemoveObject) and (pOSObject^.btType = 
            btType) then 
          begin 
            Delete(I); 
            Result := True; 
            if btType = OS_MOVINGOBJECT then 
            begin 
              pCharObject := TCharObject(pOSObject^.pObject); 
              if pCharObject.m_wObjectType = _OBJECT_HUMAN then 
                Dec(m_HumCount); 
 
            end; 
 
 
 
            pMapCellInfo^.m_xpObjectList.UnlockList; 
            Exit; 
          end; 
        end; 
      end; // for 
    end; // with 
    pMapCellInfo^.m_xpObjectList.UnlockList; 
  end; 
  Result := False; 
end; 
 
function TMirMap.AddNewObject(nX, nY: Integer; btType: Byte; pAddObject: 
  Pointer): Boolean; 
var 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
  pCharObject: TCharObject; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
    if (pMapCellInfo^.CanMove = 0) then 
    begin 
      if pMapCellInfo^.m_xpObjectList = nil then 
      begin 
        pMapCellInfo^.m_xpObjectList := TThreadList.Create; 
      end; 
      New(pOSObject); 
 
      pOSObject^.btType := btType; 
      pOSObject^.pObject := pAddObject; 
      pOSObject^.dwAddTime := GetTickCount; 
 
      if btType = OS_MOVINGOBJECT then 
      begin 
        pCharObject := TCharObject(pOSObject^.pObject); 
        if pCharObject.m_wObjectType = _OBJECT_HUMAN then 
          Inc(m_HumCount); 
 
      end; 
 
      pMapCellInfo^.m_xpObjectList.Add(pOSObject); 
      Result := True; 
      Exit; 
    end; 
  end; 
  Result := False; 
end; 
 
function TMirMap.GetObject(nX, nY: Integer): TObject; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
  pCharObject: TCharObject; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
    {  if (Integer(pMapCellInfo^.m_chFlag) and $1) = 0 then 
      begin 
        Result  := nil; 
        Exit; 
      end; 
    } 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject <> nil then 
          begin 
            if pOSObject^.btType = OS_MOVINGOBJECT then 
            begin 
              pCharObject := TCharObject(pOSObject^.pObject); 
              if (pCharObject.m_fIsDead = False) and (pCharObject.m_fIsGhost = 
                False) then 
              begin 
                Result := pCharObject; 
                pMapCellInfo^.m_xpObjectList.UnlockList; 
                Exit; 
              end; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := nil; 
end; 
 
procedure TMirMap.GetMapObject(nX, nY, nArea: Integer; var pList: TThreadList); 
var 
  I: Integer; 
  X, Y: Integer; 
  nStartX, 
    nEndX, 
    nStartY, 
    nEndY: Integer; 
  pOSObject: POSOBJECT_RCD; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pCharObject: TCharObject; 
begin 
  nStartX := nX - nArea; 
  nEndX := nX + nArea; 
  nStartY := nY - nArea; 
  nEndY := nY + nArea; 
 
  for X := nStartX to nEndX do 
  begin 
    for Y := nStartY to nEndY do 
    begin 
      pMapCellInfo := GetMapCellInfo(X, Y); 
      if pMapCellInfo <> nil then 
      begin 
        if pMapCellInfo^.m_xpObjectList <> nil then 
        begin 
          with pMapCellInfo^.m_xpObjectList.LockList do 
          begin 
            for I := 0 to COunt - 1 do // Iterate 
            begin 
              pOSObject := items[I]; 
              if pOSObject^.btType = OS_MOVINGOBJECT then 
              begin 
                pCharObject := TCharObject(pOSObject^.pObject); 
                if (pCharObject.m_fIsGhost = False) and (pCharObject.m_fIsDead = 
                  False) then 
                begin 
                  pList.Add(pCharObject); 
                end; 
              end; 
            end; // for 
          end; // with 
          pMapCellInfo^.m_xpObjectList.UnlockList; 
        end; 
      end; 
    end; 
  end; 
end; 
 
procedure TMirMap.GetAllObject(nX, nY: Integer; var pList: TThreadList); 
var 
  I: Integer; 
  pOSObject: POSOBJECT_RCD; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pCharObject: TCharObject; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
  if pMapCellInfo <> nil then 
  begin 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject^.btType = OS_MOVINGOBJECT then 
          begin 
            pCharObject := TCharObject(pOSObject^.pObject); 
            if (pCharObject.m_fIsGhost = False) and (pCharObject.m_fIsDead = 
              False) then 
            begin 
              pList.Add(pCharObject); 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; // if (PMAPCELLINFO_RCD) 
end; 
 
function TMirMap.GetDupCount(nX, nY: Integer): Integer; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pCharObject: TCharObject; 
  pOSObject: POSOBJECT_RCD; 
  nCount: Integer; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
  nCount := 0; 
 
  if pMapCellInfo <> nil then 
  begin 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject <> nil then 
          begin 
            if pOSObject^.btType = OS_MOVINGOBJECT then 
            begin 
              pCharObject := TCharObject(pOSObject^.pObject); 
              if (pCharObject.m_fIsDead = False) and (pCharObject.m_fIsGhost = 
                False) and (pCharObject.m_fHideMode) then 
              begin 
                Inc(nCount); 
              end; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := nCount; 
end; 
 
function TMirMap.GetItem(nX, nY: Integer): PMAPITEM_RCD; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
  pCharObject: TCharObject; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
  if pMapCellInfo <> nil then 
  begin 
 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject <> nil then 
          begin 
            if pOSObject^.btType = OS_ITEMOBJECT then 
            begin 
              Result := PMAPITEM_RCD(pOSObject^.pObject); 
              pMapCellInfo^.m_xpObjectList.UnlockList; 
              Exit; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := nil; 
end; 
 
function TMirMap.GetDropPosition(nOrgX, nOrgY, nRange: Integer; var nX, nY: 
  Integer): Boolean; 
var 
  I, j, ti, tj: Integer; 
  nLoonCnt: Integer; 
begin 
  nLoonCnt := (4 * nRange) * (nRange + 1); 
 
  { for I := 0 to nLoonCnt - 1 do    // Iterate 
   begin 
     nX := nOrgX + Integer(g_SearchTable[I].X); 
     nY := nOrgY + Integer(g_SearchTable[I].Y); 
 
     if GetItem(nX, nY) = nil then 
     begin 
       Result  := True; 
       Exit; 
     end; 
   end;    // for 
   } 
  for I := -nRange to nRange do 
    for j := -nRange to nRange do 
    begin 
      Randomize; 
      ti := RandomRange(-nRange, nRange); 
      tj := RandomRange(-nRange, nRange); 
      nX := nOrgX + tI; 
      nY := nOrgY + tj; 
      if GetItem(nX, nY) = nil then 
      begin 
        Result := True; 
        Exit; 
      end; 
    end; 
 
  nX := nOrgX; 
  nY := nOrgY; 
 
  Result := False; 
end; 
 
function TMirMap.GetEvent(nX, nY: Integer): TObject; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
begin 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
  if pMapCellInfo <> nil then 
  begin 
    if (Integer(pMapCellInfo^.m_chFlag) and $1) = 0 then 
    begin 
      Result := nil; 
      Exit; 
    end; 
 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject <> nil then 
          begin 
            if pOSObject^.btType = OS_EVENTOBJECT then 
            begin 
              Result := TEvent(pOSObject^.pObject); 
              pMapCellInfo^.m_xpObjectList.UnlockList; 
              Exit; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := nil; 
end; 
 
function TMirMap.CanSafeWalk(nX, nY: Integer): Boolean; 
var 
  I: Integer; 
  pMapCellInfo: PMAPCELLINFO_RCD; 
  pOSObject: POSOBJECT_RCD; 
  pEvent: TEvent; 
begin 
 
  pMapCellInfo := GetMapCellInfo(nX, nY); 
 
  if pMapCellInfo <> nil then 
  begin 
 
 
    if pMapCellInfo^.m_xpObjectList <> nil then 
    begin 
      with pMapCellInfo^.m_xpObjectList.LockList do 
      begin 
        for I := 0 to COunt - 1 do // Iterate 
        begin 
          pOSObject := items[I]; 
          if pOSObject <> nil then 
          begin 
            if pOSObject^.btType = OS_EVENTOBJECT then 
            begin 
              pEvent := TEvent(pOSObject^.pObject); 
              if pEvent.m_nDamage > 0 then 
              begin 
                Result := False; 
                pMapCellInfo^.m_xpObjectList.UnlockList; 
                Exit; 
              end; 
            end; 
          end; 
        end; // for 
      end; // with 
      pMapCellInfo^.m_xpObjectList.UnlockList; 
    end; 
  end; 
  Result := True; 
end; 
 
function TMirMap.GetMapCellInfo(nX, nY: Integer): PMAPCELLINFO_RCD; 
begin 
  if ((nX >= 0) and (nX < m_stMapFH.shWidth)) and ((nY >= 0) and (nY < 
    m_stMapFH.shHeight)) then 
  begin 
    Result := @m_pMapCellInfo[nX * m_stMapFH.shHeight + nY]; 
    Exit; 
  end; 
  Result := nil; 
end; 
 
end.