www.pudn.com > Mir2Delphi.rar > ClFunc.pas
unit ClFunc;
//辅助函数库
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
DXDraws, DirectX, DXClass, Grobal2, ScktComp, ExtCtrls, HUtil32, EdCode;
const
DR_0 = 0;
DR_1 = 1;
DR_2 = 2;
DR_3 = 3;
DR_4 = 4;
DR_5 = 5;
DR_6 = 6;
DR_7 = 7;
DR_8 = 8;
DR_9 = 9;
DR_10 = 10;
DR_11 = 11;
DR_12 = 12;
DR_13 = 13;
DR_14 = 14;
DR_15 = 15;
type
TDynamicObject = record //官蹿俊 如利
X: integer; //某腐 谅钎拌
Y: integer;
px: integer; //shiftx ,y
py: integer;
DSurface: TDirectDrawSurface;
end;
PTDynamicObject = ^TDynamicObject;
var
DropItems: TList; //lsit of TClientItem
function fmStr (str: string; len: integer): string;
function GetGoldStr (gold: integer): string;
procedure SaveBags (flname: string; pbuf: Pbyte);
procedure Loadbags (flname: string; pbuf: Pbyte);
procedure ClearBag;
function AddItemBag (cu: TClientItem): Boolean;
function UpdateItemBag (cu: TClientItem): Boolean;
function DelItemBag (iname: string; iindex: integer): Boolean;
procedure ArrangeItemBag;
procedure AddDropItem (ci: TClientItem);
function GetDropItem (iname: string; MakeIndex: integer): PTClientItem;
procedure DelDropItem (iname: string; MakeIndex: integer);
procedure AddDealItem (ci: TClientItem);
procedure DelDealItem (ci: TClientItem);
procedure MoveDealItemToBag;
procedure AddDealRemoteItem (ci: TClientItem);
procedure DelDealRemoteItem (ci: TClientItem);
function GetDistance (sx, sy, dx, dy: integer): integer;
procedure GetNextPosXY (dir: byte; var x, y:Integer);
procedure GetNextRunXY (dir: byte; var x, y:Integer);
function GetNextDirection (sx, sy, dx, dy: Integer): byte;
function GetBack (dir: integer): integer;
procedure GetBackPosition (sx, sy, dir: integer; var newx, newy: integer);
procedure GetFrontPosition (sx, sy, dir: integer; var newx, newy: integer);
function GetFlyDirection (sx, sy, ttx, tty: integer): Integer;
function GetFlyDirection16 (sx, sy, ttx, tty: integer): Integer;
function PrivDir (ndir: integer): integer;
function NextDir (ndir: integer): integer;
procedure BoldTextOut (surface: TDirectDrawSurface; x, y, fcolor, bcolor: integer; str: string);
function GetTakeOnPosition (smode: integer): integer;
function IsKeyPressed (key: byte): Boolean;
procedure AddChangeFace (recogid: integer);
procedure DelChangeFace (recogid: integer);
function IsChangingFace (recogid: integer): Boolean;
implementation
uses
clMain;
//格式化字符串为指定长度(后面添空格)
function fmStr (str: string; len: integer): string;
var i: integer;
begin
try
Result := str + ' ';
for i:=1 to len - Length(str)-1 do
Result := Result + ' ';
except
Result := str + ' ';
end;
end;
//整数转换为千位带逗号的字符串,例如1234567转换为“1,234,567”
//这里用于显示金钱数量
function GetGoldStr (gold: integer): string;
var
i, n: integer;
str: string;
begin
str := IntToStr (gold);
n := 0;
Result := '';
for i:=Length(str) downto 1 do begin
if n = 3 then begin
Result := str[i] + ',' + Result;
n := 1;
end else begin
Result := str[i] + Result;
Inc(n);
end;
end;
end;
//保存装备物品到文件
procedure SaveBags (flname: string; pbuf: Pbyte);
var
fhandle: integer;
begin
if FileExists (flname) then
fhandle := FileOpen (flname, fmOpenWrite or fmShareDenyNone)
else fhandle := FileCreate (flname);
if fhandle > 0 then begin
FileWrite (fhandle, pbuf^, sizeof(TClientItem) * MAXBAGITEMCL);
FileClose (fhandle);
end;
end;
//装载装备物品
procedure Loadbags (flname: string; pbuf: Pbyte);
var
fhandle: integer;
begin
if FileExists (flname) then begin
fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone);
if fhandle > 0 then begin
FileRead (fhandle, pbuf^, sizeof(TClientItem) * MAXBAGITEMCL);
FileClose (fhandle);
end;
end;
end;
//清除物品
procedure ClearBag;
var
i: integer;
begin
for i:=0 to MAXBAGITEMCL-1 do
ItemArr[i].S.Name := '';
end;
//添加物品
function AddItemBag (cu: TClientItem): Boolean;
var
i: integer;
begin
Result := FALSE;
//检查要添加的物品是否已经存在
for i:=0 to MAXBAGITEMCL-1 do begin
if (ItemArr[i].MakeIndex = cu.MakeIndex) and (ItemArr[i].S.Name = cu.S.Name) then begin
exit; //儡惑..
end;
end;
if cu.S.Name = '' then exit;
if cu.S.StdMode <= 3 then begin //可以使用的物品,首先放在快捷物品栏
for i:=0 to 5 do //前面6格显示在快捷物品栏上
if ItemArr[i].S.Name = '' then begin //找一个空档放下
ItemArr[i] := cu;
Result := TRUE;
exit;
end;
end;
for i:=6 to MAXBAGITEMCL-1 do begin
if ItemArr[i].S.Name = '' then begin
ItemArr[i] := cu;
Result := TRUE;
break;
end;
end;
ArrangeItembag;
end;
//用当前的物品属性替代已经存在的该物品属性
function UpdateItemBag (cu: TClientItem): Boolean;
var
i: integer;
begin
Result := FALSE;
for i:=MAXBAGITEMCL-1 downto 0 do begin
if (ItemArr[i].S.Name = cu.S.Name) and (ItemArr[i].MakeIndex = cu.MakeIndex) then begin
ItemArr[i] := cu; //诀单捞飘
Result := TRUE;
break;
end;
end;
end;
//删除指定的物品
function DelItemBag (iname: string; iindex: integer): Boolean;
var
i: integer;
begin
Result := FALSE;
for i:=MAXBAGITEMCL-1 downto 0 do begin
if (ItemArr[i].S.Name = iname) and (ItemArr[i].MakeIndex = iindex) then begin
FillChar (ItemArr[i], sizeof(TClientItem), #0);
Result := TRUE;
break;
end;
end;
ArrangeItembag;
end;
//整理物品包
procedure ArrangeItemBag;
var
i, k: integer;
begin
//吝汗等 酒捞袍捞 乐栏搁 绝矩促.
for i:=0 to MAXBAGITEMCL-1 do begin
if ItemArr[i].S.Name <> '' then begin //清除相同的物品
for k:=i+1 to MAXBAGITEMCL-1 do begin
if (ItemArr[i].S.Name = ItemArr[k].S.Name) and (ItemArr[i].MakeIndex = ItemArr[k].MakeIndex) then begin
FillChar (ItemArr[k], sizeof(TClientItem), #0);
end;
end;
{for k:=0 to 9 do begin
if (ItemArr[i].S.Name = DealItems[k].S.Name) and (ItemArr[i].MakeIndex = DealItems[k].MakeIndex) then begin
FillChar (ItemArr[i], sizeof(TClientItem), #0);
//FillChar (DealItems[k], sizeof(TClientItem), #0);
end;
end; }
//若有移动的物品
if (ItemArr[i].S.Name = MovingItem.Item.S.Name) and (ItemArr[i].MakeIndex = MovingItem.Item.MakeIndex) then begin
MovingItem.Index := 0;
MovingItem.Item.S.Name := '';
end;
end;
end;
//6样特殊物品栏
//啊规狼 救焊捞绰 何盒俊 乐栏搁 缠绢 棵赴促.
for i:=46 to MAXBAGITEMCL-1 do begin
if ItemArr[i].S.Name <> '' then begin
for k:=6 to 45 do begin
if ItemArr[k].S.Name = '' then begin
ItemArr[k] := ItemArr[i];
ItemArr[i].S.Name := '';
break;
end;
end;
end;
end;
end;
{----------------------------------------------------------}
//添加跌落物品
procedure AddDropItem (ci: TClientItem);
var
pc: PTClientItem;
begin
new (pc);
pc^ := ci;
DropItems.Add (pc);
end;
//获取跌落物品
function GetDropItem (iname: string; MakeIndex: integer): PTClientItem;
var
i: integer;
begin
Result := nil;
for i:=0 to DropItems.Count-1 do begin
if (PTClientItem(DropItems[i]).S.Name = iname) and (PTClientItem(DropItems[i]).MakeIndex = MakeIndex) then begin
Result := PTClientItem(DropItems[i]);
break;
end;
end;
end;
//删除跌落物品
procedure DelDropItem (iname: string; MakeIndex: integer);
var
i: integer;
begin
for i:=0 to DropItems.Count-1 do begin
if (PTClientItem(DropItems[i]).S.Name = iname) and (PTClientItem(DropItems[i]).MakeIndex = MakeIndex) then begin
Dispose (PTClientItem(DropItems[i]));
DropItems.Delete (i);
break;
end;
end;
end;
{----------------------------------------------------------}
procedure AddDealItem (ci: TClientItem);
var
i: integer;
begin
for i:=0 to 10-1 do begin
if DealItems[i].S.Name = '' then begin
DealItems[i] := ci;
break;
end;
end;
end;
procedure DelDealItem (ci: TClientItem);
var
i: integer;
begin
for i:=0 to 10-1 do begin
if (DealItems[i].S.Name = ci.S.Name) and (DealItems[i].MakeIndex = ci.MakeIndex) then begin
FillChar (DealItems[i], sizeof(TClientItem), #0);
break;
end;
end;
end;
procedure MoveDealItemToBag;
var
i: integer;
begin
for i:=0 to 10-1 do begin
if DealItems[i].S.Name <> '' then
AddItemBag (DealItems[i]);
end;
FillChar (DealItems, sizeof(TClientItem)*10, #0);
end;
procedure AddDealRemoteItem (ci: TClientItem);
var
i: integer;
begin
for i:=0 to 20-1 do begin
if DealRemoteItems[i].S.Name = '' then begin
DealRemoteItems[i] := ci;
break;
end;
end;
end;
procedure DelDealRemoteItem (ci: TClientItem);
var
i: integer;
begin
for i:=0 to 20-1 do begin
if (DealRemoteItems[i].S.Name = ci.S.Name) and (DealRemoteItems[i].MakeIndex = ci.MakeIndex) then begin
FillChar (DealRemoteItems[i], sizeof(TClientItem), #0);
break;
end;
end;
end;
{----------------------------------------------------------}
//计算两点间的距离(X或Y方向)
function GetDistance (sx, sy, dx, dy: integer): integer;
begin
Result := _MAX(abs(sx-dx), abs(sy-dy));
end;
//根据方向和当前位置确定下一个位置坐标(位移量=1)
procedure GetNextPosXY (dir: byte; var x, y:Integer);
begin
case dir of
DR_UP: begin x := x; y := y-1; end;
DR_UPRIGHT: begin x := x+1; y := y-1; end;
DR_RIGHT: begin x := x+1; y := y; end;
DR_DOWNRIGHT: begin x := x+1; y := y+1; end;
DR_DOWN: begin x := x; y := y+1; end;
DR_DOWNLEFT: begin x := x-1; y := y+1; end;
DR_LEFT: begin x := x-1; y := y; end;
DR_UPLEFT: begin x := x-1; y := y-1; end;
end;
end;
//根据方向和当前位置确定下一个位置坐标(位移量=2)
procedure GetNextRunXY (dir: byte; var x, y:Integer);
begin
case dir of
DR_UP: begin x := x; y := y-2; end;
DR_UPRIGHT: begin x := x+2; y := y-2; end;
DR_RIGHT: begin x := x+2; y := y; end;
DR_DOWNRIGHT: begin x := x+2; y := y+2; end;
DR_DOWN: begin x := x; y := y+2; end;
DR_DOWNLEFT: begin x := x-2; y := y+2; end;
DR_LEFT: begin x := x-2; y := y; end;
DR_UPLEFT: begin x := x-2; y := y-2; end;
end;
end;
//根据两点计算移动的方向
function GetNextDirection (sx, sy, dx, dy: Integer): byte;
var
flagx, flagy: integer;
begin
Result := DR_DOWN;
if sx < dx then flagx := 1
else if sx = dx then flagx := 0
else flagx := -1;
if abs(sy-dy) > 2
then if (sx >= dx-1) and (sx <= dx+1) then flagx := 0;
if sy < dy then flagy := 1
else if sy = dy then flagy := 0
else flagy := -1;
if abs(sx-dx) > 2 then if (sy > dy-1) and (sy <= dy+1) then flagy := 0;
if (flagx = 0) and (flagy = -1) then Result := DR_UP;
if (flagx = 1) and (flagy = -1) then Result := DR_UPRIGHT;
if (flagx = 1) and (flagy = 0) then Result := DR_RIGHT;
if (flagx = 1) and (flagy = 1) then Result := DR_DOWNRIGHT;
if (flagx = 0) and (flagy = 1) then Result := DR_DOWN;
if (flagx = -1) and (flagy = 1) then Result := DR_DOWNLEFT;
if (flagx = -1) and (flagy = 0) then Result := DR_LEFT;
if (flagx = -1) and (flagy = -1) then Result := DR_UPLEFT;
end;
//根据当前方向获得转身后的方向
function GetBack (dir: integer): integer;
begin
Result := DR_UP;
case dir of
DR_UP: Result := DR_DOWN;
DR_DOWN: Result := DR_UP;
DR_LEFT: Result := DR_RIGHT;
DR_RIGHT: Result := DR_LEFT;
DR_UPLEFT: Result := DR_DOWNRIGHT;
DR_UPRIGHT: Result := DR_DOWNLEFT;
DR_DOWNLEFT: Result := DR_UPRIGHT;
DR_DOWNRIGHT: Result := DR_UPLEFT;
end;
end;
//根据当前坐标和方向获得后退的坐标
procedure GetBackPosition (sx, sy, dir: integer; var newx, newy: integer);
begin
newx := sx;
newy := sy;
case dir of
DR_UP: newy := newy+1;
DR_DOWN: newy := newy-1;
DR_LEFT: newx := newx+1;
DR_RIGHT: newx := newx-1;
DR_UPLEFT:
begin
newx := newx + 1;
newy := newy + 1;
end;
DR_UPRIGHT:
begin
newx := newx - 1;
newy := newy + 1;
end;
DR_DOWNLEFT:
begin
newx := newx + 1;
newy := newy - 1;
end;
DR_DOWNRIGHT:
begin
newx := newx - 1;
newy := newy - 1;
end;
end;
end;
//根据当前位置和方向获得前进一步的坐标
procedure GetFrontPosition (sx, sy, dir: integer; var newx, newy: integer);
begin
newx := sx;
newy := sy;
case dir of
DR_UP: newy := newy-1;
DR_DOWN: newy := newy+1;
DR_LEFT: newx := newx-1;
DR_RIGHT: newx := newx+1;
DR_UPLEFT:
begin
newx := newx - 1;
newy := newy - 1;
end;
DR_UPRIGHT:
begin
newx := newx + 1;
newy := newy - 1;
end;
DR_DOWNLEFT:
begin
newx := newx - 1;
newy := newy + 1;
end;
DR_DOWNRIGHT:
begin
newx := newx + 1;
newy := newy + 1;
end;
end;
end;
//根据两点位置获得飞行方向(8个方向)
function GetFlyDirection (sx, sy, ttx, tty: integer): Integer;
var
fx, fy: Real;
begin
fx := ttx - sx;
fy := tty - sy;
sx := 0;
sy := 0;
Result := DR_DOWN;
if fx=0 then begin //两点的X坐标相等
if fy < 0 then Result := DR_UP
else Result := DR_DOWN;
exit;
end;
if fy=0 then begin //两点的Y坐标相等
if fx < 0 then Result := DR_LEFT
else Result := DR_RIGHT;
exit;
end;
if (fx > 0) and (fy < 0) then begin
if -fy > fx*2.5 then Result := DR_UP
else if -fy < fx/3 then Result := DR_RIGHT
else Result := DR_UPRIGHT;
end;
if (fx > 0) and (fy > 0) then begin
if fy < fx/3 then Result := DR_RIGHT
else if fy > fx*2.5 then Result := DR_DOWN
else Result := DR_DOWNRIGHT;
end;
if (fx < 0) and (fy > 0) then begin
if fy < -fx/3 then Result := DR_LEFT
else if fy > -fx*2.5 then Result := DR_DOWN
else Result := DR_DOWNLEFT;
end;
if (fx < 0) and (fy < 0) then begin
if -fy > -fx*2.5 then Result := DR_UP
else if -fy < -fx/3 then Result := DR_LEFT
else Result := DR_UPLEFT;
end;
end;
//根据两点位置获得飞行方向(16个方向)
function GetFlyDirection16 (sx, sy, ttx, tty: integer): Integer;
var
fx, fy: Real;
begin
fx := ttx - sx;
fy := tty - sy;
sx := 0;
sy := 0;
Result := 0;
if fx=0 then begin
if fy < 0 then Result := 0
else Result := 8;
exit;
end;
if fy=0 then begin
if fx < 0 then Result := 12
else Result := 4;
exit;
end;
if (fx > 0) and (fy < 0) then begin
Result := 4;
if -fy > fx/4 then Result := 3;
if -fy > fx/1.9 then Result := 2;
if -fy > fx*1.4 then Result := 1;
if -fy > fx*4 then Result := 0;
end;
if (fx > 0) and (fy > 0) then begin
Result := 4;
if fy > fx/4 then Result := 5;
if fy > fx/1.9 then Result := 6;
if fy > fx*1.4 then Result := 7;
if fy > fx*4 then Result := 8;
end;
if (fx < 0) and (fy > 0) then begin
Result := 12;
if fy > -fx/4 then Result := 11;
if fy > -fx/1.9 then Result := 10;
if fy > -fx*1.4 then Result := 9;
if fy > -fx*4 then Result := 8;
end;
if (fx < 0) and (fy < 0) then begin
Result := 12;
if -fy > -fx/4 then Result := 13;
if -fy > -fx/1.9 then Result := 14;
if -fy > -fx*1.4 then Result := 15;
if -fy > -fx*4 then Result := 0;
end;
end;
//按逆时针转动一个方向后的方向
function PrivDir (ndir: integer): integer;
begin
if ndir - 1 < 0 then Result := 7
else Result := ndir-1;
end;
//按顺时针转动一个方向后的方向
function NextDir (ndir: integer): integer;
begin
if ndir + 1 > 7 then Result := 0
else Result := ndir+1;
end;
//着重显示文字(以bcolor色加文字边框),效果如镂空
procedure BoldTextOut (surface: TDirectDrawSurface; x, y, fcolor, bcolor: integer; str: string);
begin
with surface do begin
Canvas.Font.Color := bcolor;
Canvas.TextOut (x-1, y, str);
Canvas.TextOut (x+1, y, str);
Canvas.TextOut (x, y-1, str);
Canvas.TextOut (x, y+1, str);
Canvas.Font.Color := fcolor;
Canvas.TextOut (x, y, str);
end;
end;
function GetTakeOnPosition (smode: integer): integer;
begin
Result := -1;
case smode of //StdMode
5, 6: //公扁
Result := U_WEAPON;
10, 11:
Result := U_DRESS;
15,16:
Result := U_HELMET;
19,20,21:
Result := U_NECKLACE;
22,23:
Result := U_RINGL;
24,26:
Result := U_ARMRINGR;
25:
Result := U_ARMRINGL;
30:
Result := U_RIGHTHAND;
end;
end;
function IsKeyPressed (key: byte): Boolean;
var
keyvalue: TKeyBoardState;
begin
Result := FALSE;
FillChar(keyvalue, sizeof(TKeyboardState), #0);
if GetKeyboardState (keyvalue) then
if (keyvalue[key] and $80) <> 0 then
Result := TRUE;
end;
procedure AddChangeFace (recogid: integer);
begin
ChangeFaceReadyList.Add (pointer(recogid));
end;
procedure DelChangeFace (recogid: integer);
var
i: integer;
begin
for i:=0 to ChangeFaceReadyList.Count-1 do begin
if integer(ChangeFaceReadyList[i]) = recogid then begin
ChangeFaceReadyList.Delete (i);
break;
end;
end;
end;
function IsChangingFace (recogid: integer): Boolean;
var
i: integer;
begin
Result := FALSE;
for i:=0 to ChangeFaceReadyList.Count-1 do begin
if integer(ChangeFaceReadyList[i]) = recogid then begin
Result := TRUE;
break;
end;
end;
end;
Initialization
DropItems := TList.Create;
Finalization
DropItems.Free;
end.