找传奇、传世资源到传世资源站!

传奇世界AFT3假人引擎源代码,供参考

2020.9.18 文章收藏 3166 编辑

unit ObjAI;

interface

uses
Windows, Classes, Grobal2, ObjBase, sysutils,MapPoint ,Envir,PathFind,PlayObject,IniFiles;

const
QueueMagicOfJob0 : set of byte = [25, 43]; //半月弯刀--打自己前方180度范围坐标,1格坐标 抱月刀-
QueueMagicOfJob1 : set of byte = [9, 10, 22, 23, 24, 33, 50, 51, 52, 53, 54, 73];
SingleMagicOfJob0 : set of byte = [7, 12, 26, 44]; //攻杀剑法、刺杀剑术、烈火剑法、雷霆剑
SingleMagicOfJob1 : set of byte = [1, 5, 11, 49, 71]; //小火球、火炎刀、雷电术、冰箭术、狂龙紫电
SingleMagicOfJob2 : set of byte = [13, 67]; //灵魂道符、幽冥火咒

type
TAIPlayObject = class(Tplayobject)
n54C: Integer; //0x54C
//0x550
m_dwuseskilltick: LongWord;

bo554: Boolean; //0x554
m_boDupMode: Boolean; //0x555
m_btUsePoison: integer;
toonear: boolean;
toofar: boolean;
ADDHPMODE: BOOLEAN;
start_map: string;
start_x,start_y:Integer ;
m_sConfigListFileName: string;
m_sFilePath: string;
m_sConfigFileName: string;
m_sHeroConfigFileName: string;
m_dwAutoAddHealthTick, m_nNextPOISONTime, m_nNextAddHpTime, m_nNextPushTime, m_nNextQueueTime, m_dwEscapeTime, m_nNextEscapeTime: dword;
m_dwPiosonTick, m_dwAddHpTick, m_dwPushTick, m_dwclearnoatackTick, m_nNextSkillTime,m_dwThinkTick : LongWord; //0x550
m_noatcktActors: TList; //0x408 //可见范围内的人物列表

m_boAIStart: Boolean;
m_ManagedEnvir: TEnvirnoment; //挂机地图
m_PointManager: TPointManager;
m_Path: TPath;
m_nPostion: Integer;
m_nround: Integer;
m_nMoveFailCount: Integer;
nDieDropUseItemRate:Integer;
m_SelItemObject: pTMapItem;
m_dwSearchTargetTick: LongWord;
m_SkillUseTick: array[0..80 - 1] of LongWord; //魔法使用间隔
m_nerr : integer;
m_RunPos: TRunPos;
m_boSelSelf: Boolean;
lasttarget:TBaseObject;
lasttargettick: LongWord;

m_nIncSelfHealthCount: Integer;
private
function Think: Boolean;
public
constructor Create(); override;
destructor Destroy; override;
function Operate(ProcessMsg: pTProcessMessage): Boolean; override; //FFFC
function CanWalk(nCurrX, nCurrY, nTargetX, nTargetY: Integer; nDir: Integer; var nStep: Integer; boFlag: Boolean): Boolean;
//FFEB
procedure SearchTargetxy();
function IsProperTarget(BaseObject: TBaseObject): Boolean;override;
function IsGotoXY(X1, Y1, X2, Y2: Integer): Boolean;
function GetMasterRange(nTargetX, nTargetY: Integer): Integer; //FFEB
procedure Run; override;
procedure StartAI(PathType: TPathType);
procedure Stop;
procedure Die; override;
procedure MakeGhost(); override;
function StartAttack(wMagIdx: Integer): Boolean; virtual;
function WarrAttackTarget(wMagIdx, wHitMode: Word): Boolean; virtual; {物理攻击}
function WarrorAttackTarget(wMagIdx: Integer): Boolean; virtual; {战士攻击}
function WizardAttackTarget(wMagIdx: Integer): Boolean; virtual; {法师攻击}
function TaoistAttackTarget(wMagIdx: Integer): Boolean; virtual; {道士攻击}
function CanAttack(BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean; overload;
function CanAttack(nCurrX, nCurrY: Integer; BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean; overload;
function GetAttackDir(BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean; overload;
function SelectMagic(): Integer;
function GetRandomConfigFileName: string;
function FindMagic(sMagicName: string): pTUserMagic;
procedure Initialize;

function DoThink(wMagicID: Word): Integer; virtual;
function ActThink(wMagicID: Word): Boolean; virtual;
function HaveSingleMagic(AJob: byte): Boolean;
function GetAttackCount: integer;
function getEscapeMagic(AJob: byte): pTMagic;
function HaveQueueMagic(AJob: byte): Boolean;
function GotoNextOne(nX, nY: Integer; boRun: Boolean): Boolean;
function WalkToNext(nX, nY: Integer): Boolean;
function RunToNext(nX, nY: Integer): Boolean;
function GotoNext(nX, nY: Integer; boRun: Boolean): Boolean;
function CanLineAttack(nStep: Integer): Boolean; overload;
function CanLineAttack(nCurrX, nCurrY: Integer): Boolean; overload;
function AllowUseMagic(wMagIdx: Word): Boolean;
function SkillAttack(UserMagic: pTuserMagic; TargetCret: TBaseObject): boolean;
function SkillAttackOfSoldier(UserMagic: pTuserMagic; nDir: word; TargetCret: TBaseObject): boolean;
function SkillDamage(UserMagic: pTuserMagic; TargetCret: TBaseObject): boolean;
procedure Wonderingai();
function magAttackTarget(): Boolean; virtual; //FFEB
function AttackTarget(): Boolean; virtual; //FFEB
function StartPickUpItem(nPickUpTime: Integer): Boolean;
function IsUseAttackMagic(): Boolean; //检测是否可以使用攻击魔法
procedure UpdatenoatcktActors(BaseObject: TBaseObject);
function canatackTarget(BaseObject: TBaseObject): Boolean;
end;

implementation

uses
UsrEngn, HUtil32,M2Share;
{ TAIPlayObject }

function TAIPlayObject.magAttackTarget: Boolean;
var
bt06 : Byte;
nX, nY : INTEGER;
UserMagic : pTUserMagic;
doskill : boolean;
begin
Result := False;
toonear := false;
if m_TargetCret <> nil then
begin
if (abs(m_nCurrX - m_TargetCret.m_nCurrX) <= 5) and (abs(m_nCurry - m_TargetCret.m_nCurry) <= 5) then
begin // GetAttackDir(m_TargetCret,bt06)
if Integer(GetTickCount - m_dwHitTick) > m_nNextHitTime then
begin
m_dwHitTick := GetTickCount();
m_dwTargetFocusTick := GetTickCount();

if not toonear then
begin //距离够了
doskill := false;

UserMagic := GetMagicInfo(31); //nskill); // 狂龙紫电 kk2017 魔法盾相关?
if (UserMagic <> nil) and (not doskill) then
// if MagicManager.DoSpell(Self,UserMagic,m_TargetCret.m_nCurrX,m_TargetCret.m_nCurrY,m_TargetCret) then
if DoSpell(UserMagic, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret) then
Result := True;

BreakHolySeizeMode();
end; //距离够了

// ClientSpellXY(wIdent:Word;nKey:Integer;nTargetX, nTargetY:Integer;TargeTBaseObject: TBaseObject;boLateDelivery:Boolean;var dwDelayTime:LongWord)
// Attack1(m_TargetCret,bt06); //FFED
{ if m_btUsePoison>=0 then begin
if random(5)<2 then m_TargetCret.MakePosion(m_btUsePoison,_max(5,loword( m_WAbil.sC)),_max(5,loword( m_WAbil.mC))) ;
end; }
{ if m_btusefire >=0 then begin
GetFrontPosition(nX,nY);
Makefire(nX,nY,BT06);

end;
}

end;

end
else
begin
if m_TargetCret.m_PEnvir = m_PEnvir then
begin
if (abs(m_nCurrX - m_TargetCret.m_nCurrX) >= 5) and (abs(m_nCurry - m_TargetCret.m_nCurry) >= 5) then
SetTargetXY(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY); {0FFF0h}
//004A8FE3
end
else
begin
DelTargetCreat(); {0FFF1h}
//004A9009
end;
end;
end;
end;
function TAIPlayObject.AttackTarget: Boolean;
var
bt06 : Byte;
nX, nY : INTEGER;
doskill : boolean;
UserMagic : pTUserMagic;
skilltype : integer;
begin
Result := False;
doskill := false;
if m_TargetCret <> nil then
begin
if GetAttackDir(m_TargetCret, bt06) then
begin
if Integer(GetTickCount - m_dwHitTick) > m_nNextHitTime then
begin
m_dwHitTick := GetTickCount();
m_dwTargetFocusTick := GetTickCount();
skilltype := 0;
case nskill of
7:
skilltype := 1; //攻杀剑法
12:
skilltype := 4; //刺杀剑术
25:
skilltype := 5; //半月弯刀
26:
skilltype := 7; //烈火剑法
59:
skilltype := 10; //破击剑法
60:
skilltype := 11; // 破盾斩
62:
skilltype := 62; //突斩
27:
skilltype := 27; //野蛮冲撞
end;
if (not doskill) and (skilltype in [1, 4, 5, 7, 10, 11]) then
Attack1(m_TargetCret, skilltype, bt06); //FFED //技能烈火

if (not doskill) and (skilltype in [62]) then
begin
UserMagic := GetMagicInfo(62);
if UserMagic <> nil then
useDoMotaebo(UserMagic, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret);
end;
// Attack1(m_TargetCret,skilltype,bt06); //FFED //技能烈火
// if m_btUsePoison>=0 then begin
// if random(5)<2 then m_TargetCret.MakePosion(m_btUsePoison,_max(5,loword( m_WAbil.sC)),_max(5,loword( m_WAbil.mC))) ;
// end;
{ if m_btusefire >=0 then begin
GetFrontPosition(nX,nY);
Makefire(nX,nY,BT06);

end;
}
BreakHolySeizeMode();
end;
Result := True;
end
else
begin
if m_TargetCret.m_PEnvir = m_PEnvir then
begin
SetTargetXY(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY); {0FFF0h}
//004A8FE3
end
else
begin
DelTargetCreat(); {0FFF1h}
//004A9009
end;
end;
end;
end;

procedure TAIPlayObject.Wonderingai();

var
nX, nY,ncode,nDir,bx,by: Integer;
begin
if m_boAIStart and
(m_TargetCret = nil) and
(not m_boGhost) and
(not m_boDeath) and
(not m_boFixedHideMode) and
(not m_boStoneMode) and
(m_wStatusTimeArr[POISON_STONE] = 0) then begin
try

if (abs(m_nCurrX - start_x) + abs(m_nCurry - start_y) >m_nround) then begin

if m_nMoveFailCount> 10 then begin
MapRandomMove(m_PEnvir.sMapName, 0);
m_nMoveFailCount:=0;
end;

bx:= start_x+4-random(8) ;
by:= start_y+4-random(8) ;
nDir := GetNextDirection(m_nCurrX, m_nCurrY, bx, by);
m_PEnvir.GetNextPosition(start_x, start_y, nDir, 2, m_nTargetX, m_nTargetY);

if not runto(nDir, false, m_nTargetX, m_nTargetY) then GotoTargetXY();
Inc(m_nMoveFailCount);
// MainOutMessage(Format('%s往回:(%d / %d/ %d)', [m_sCharName,start_x, start_y,m_nround]));
exit;
// MainOutMessage(Format('%s往回走:(%d / %d)', [m_sCharName,start_x, start_y]));
end;

//if not m_PointManager.Finish then begin
nX := m_nCurrX;
nY := m_nCurrY;
// MainOutMessage(Format('TAIObject.Wondering0:(%d / %d)', [nX, nY]));
//m_PointManager.SetThroughPoint(m_nCurrX, m_nCurrY);
if (Length(m_Path) > 0) and (m_nPostion < Length(m_Path)) then begin
if not GotoNextOne(m_Path[m_nPostion].X, m_Path[m_nPostion].Y, True) then begin
m_Path := nil;
m_nPostion := -1;
Inc(m_nMoveFailCount);
Inc(m_nPostion);
end else begin
m_nMoveFailCount := 0;
//MainOutMessage(m_sCharName + ' GotoNextOne FindPath:' + IntToStr(Length(m_Path)));
Exit;
end;
end else begin
m_Path := nil;
m_nPostion := -1;
end;
ncode:=0;
if m_PointManager.GetPoint(nX, nY) then begin
if (abs(nX - m_nCurrX) > 2) or (abs(nY - m_nCurrY) > 2) then begin
g_FindPath.BaseObject := Self;
m_Path := g_FindPath.FindPath(m_PEnvir, m_nCurrX, m_nCurrY, nX, nY, True, False);
m_nPostion := 0;
ncode:=2;
//MainOutMessage(m_sCharName + ' FindPath:' + IntToStr(Length(m_Path)));
if (Length(m_Path) > 0) and (m_nPostion < Length(m_Path)) then begin
if not GotoNextOne(m_Path[m_nPostion].X, m_Path[m_nPostion].Y, True) then begin
m_Path := nil;
m_nPostion := -1;
Inc(m_nMoveFailCount);
end else begin
m_nMoveFailCount := 0;
Inc(m_nPostion);
Exit;
end;
ncode:=3;
end else begin
m_Path := nil;
m_nPostion := -1;
Inc(m_nMoveFailCount);
end;
end else begin
if GotoNextOne(nX, nY, True) then begin
m_nMoveFailCount := 0;
end else begin
Inc(m_nMoveFailCount);
end;
end;
//MainOutMessage(Format('%s TAIObject.Wondering1:(%d / %d)', [m_sCharName, nX, nY]));
//if GotoNextOne(nX, nY, True) then MainOutMessage(Format('%s TAIObject.Wondering2:(%d / %d)', [m_sCharName, nX, nY])) else MainOutMessage(Format('%s TAIObject.Wondering3:(%d / %d)', [m_sCharName, nX, nY]));
end else Stop;
//end else Stop;
except

MainOutMessage(Format('Wonderingai:(%d )', [ncode]));

end;

end;

// if m_nMoveFailCount >= 3 then Stop;
end;

function TAIPlayObject.DoThink(wMagicID: Word): Integer;
function TargetNeedRunPos(): Boolean;
begin
Result := (m_TargetCret.m_btRaceServer = RC_PLAYOBJECT) { or (not InMasterRange(8))};
end;

function CanRunPos(nAttackCount: Integer): Boolean;
begin
Result := (m_RunPos.nAttackCount >= nAttackCount) {and (m_RunPos.nCurrX = m_nCurrX) and (m_RunPos.nCurrY = m_nCurrY)};
end;

 

function MagPushArround(MagicID: Integer): Boolean;
var
I: Integer;
ActorObject: TBaseObject;
BaseObject: TBaseObject;
btNewDir: Byte;
nTargetX, nTargetY: Integer;
begin
Result := False;
if (m_TargetCret <> nil) and (m_Abil.Level > m_TargetCret.m_Abil.Level) and
(abs(m_nCurrX - m_TargetCret.m_nCurrX) <= 1) and (abs(m_nCurrY - m_TargetCret.m_nCurrY) <= 1) then begin
btNewDir := GetNextDirection(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_nCurrX, m_nCurrY);
if m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, GetBackDir(btNewDir), 1, nTargetX, nTargetY) then begin
Result := m_PEnvir.CanWalk(nTargetX, nTargetY, True) and m_PEnvir.CanWalkOfEvent(Self, nTargetX, nTargetY);
end;
if Result then Exit;
end;
if wMagicID = MagicID then begin
for I := 0 to m_VisibleActors.Count - 1 do begin
ActorObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[I]).BaseObject);
if (abs(m_nCurrX - ActorObject.m_nCurrX) <= 1) and (abs(m_nCurrY - ActorObject.m_nCurrY) <= 1) then begin
if (not ActorObject.m_boDeath) and (ActorObject <> Self) and IsProperTarget(ActorObject) then begin
if (m_Abil.Level > ActorObject.m_Abil.Level) and (not ActorObject.m_boStickMode) then begin
btNewDir := GetNextDirection(ActorObject.m_nCurrX, ActorObject.m_nCurrY, m_nCurrX, m_nCurrY);
if m_PEnvir.GetNextPosition(ActorObject.m_nCurrX, ActorObject.m_nCurrY, GetBackDir(btNewDir), 1, nTargetX, nTargetY) then begin
if m_PEnvir.CanWalk(nTargetX, nTargetY, True) and m_PEnvir.CanWalkOfEvent(Self, nTargetX, nTargetY) then begin
Result := True;
Break;
end;
end;
end;
end;
end;
end;
end;
end;

var
I: Integer;
btDir: Byte;
nStep: Integer;
nRange: Integer;
begin
Result := -1;

case m_btJob of
0: begin
//1=野蛮冲撞 2=无法攻击到目标需要移动 3=走位
begin
nRange := 1;
if (wMagicID = 58) or (wMagicID = 77) then nRange := 4;
if (wMagicID = 12) then nRange := 2;
//if (wMagicID in [60]) then nRange := 6;
//if (wMagicID in [60, 61, 62]) then nRange := 12;
if (wMagicID in [60]) then nRange := 6;

Result := 2;
if (wMagicID in [61, 62]) or CanAttack(m_TargetCret, nRange, btDir) then begin
Result := 0;
end;

if (Result = 0) and (not (wMagicID in [60, 61, 62])) then begin
if TargetNeedRunPos then begin
if CanRunPos(5) then
Result := 5;
end else begin
if CanRunPos(20) then
Result := 5;
end;
end;
end;
end;
1: begin
if (wMagicID = 8) and MagPushArround(wMagicID) then Exit;
//1=躲避 2=追击 3=魔法直线攻击不到目标 4=无法攻击到目标需要移动 5=走位
if IsUseAttackMagic then begin
if GetNearTargetCount > 0 then begin
Result := 1;
end else
if ((abs(m_TargetCret.m_nCurrX - m_nCurrX) > 6) or (abs(m_TargetCret.m_nCurrY - m_nCurrY) > 6)) then begin
Result := 2;
end else
//if (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2]) and (not CanWalk(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, -1, nStep, True)) then begin
if (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2]) and (not CanAttack(m_TargetCret, 10, btDir)) then begin
Result := 3;
end else
if {((GetTickCount - m_dwStationTick) > 1000 * 10) and} TargetNeedRunPos and CanRunPos(5) then begin
Result := 5;
end;
end else begin
if (not GetAttackDir(m_TargetCret, 1, btDir)) then begin
Result := 4;
end;
end;
//end;
end;
2: begin
if (wMagicID = 48) and MagPushArround(wMagicID) then Exit;
if IsUseAttackMagic then begin
if GetNearTargetCount > 0 then begin
Result := 1;
end else
if ((abs(m_TargetCret.m_nCurrX - m_nCurrX) > 6) or (abs(m_TargetCret.m_nCurrY - m_nCurrY) > 6)) then begin
Result := 2;
end else
//if (wMagicID = SKILL_FIRECHARM) and (not CanWalk(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, -1, nStep, True)) then begin
if (wMagicID = SKILL_FIRECHARM) and (not CanAttack(m_TargetCret, 10, btDir)) then begin
Result := 3;
end else
if {((GetTickCount - m_dwStationTick) > 1000 * 10) and} TargetNeedRunPos and CanRunPos(5) then begin
Result := 5;
end;
end else begin
if (not GetAttackDir(m_TargetCret, 1, btDir)) then begin
Result := 4;
end;
end;
end;
end;
end;

function TAIPlayObject.IsUseAttackMagic(): Boolean; //检测是否可以使用攻击魔法
var
UserMagic: pTUserMagic;
I: Integer;
begin
Result := False;
case m_btJob of
0: Result := True;
1: begin
for I := 0 to m_MagicList.Count - 1 do begin
UserMagic := m_MagicList.Items[I];
case UserMagic.wMagIdx of
SKILL_FIREBALL {1},
SKILL_FIREBALL2,
SKILL_FIRE,
SKILL_SHOOTLIGHTEN,
SKILL_LIGHTENING,
SKILL_EARTHFIRE,
SKILL_FIREBOOM,
SKILL_LIGHTFLOWER,
SKILL_SNOWWIND,
SKILL_GROUPLIGHTENING,
SKILL_47: begin
Result := True;
Break;
end;
end;
end;
end;
2: begin
for I := 0 to m_MagicList.Count - 1 do begin
UserMagic := m_MagicList.Items[I];
if UserMagic.MagicInfo.btJob in [2, 99] then begin
case UserMagic.wMagIdx of
SKILL_AMYOUNSUL {6 施毒术}, SKILL_GROUPAMYOUNSUL {38 群体施毒术}: begin //需要毒药
Result := true;
if Result then Break;
end;
SKILL_FIRECHARM: begin //需要符
Result := true;
if Result then Break;
end;

end;
end;
end;
end;
end;
end;

function TAIPlayObject.AllowUseMagic(wMagIdx: Word): Boolean;
var
UserMagic: pTUserMagic;
nSpellPoint: Integer;
begin
Result := False;
if (wMagIdx = 22) and g_Config.boDisableInSafeZoneFireCross and (m_TargetCret <> nil) and InSafeZone(m_PEnvir, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY) then begin
Exit;
end;

if m_WAbil.MP<200 then m_WAbil.MP:=200;
UserMagic := GetMagicInfo(wMagIdx);
if UserMagic <> nil then begin
if not MagicManager.IsWarrSkill(UserMagic.wMagIdx) then begin
if (UserMagic.btKey > 0) or m_boAI then begin
nSpellPoint := GetSpellPoint(UserMagic);
// MainOutMessage('耗魔法:'+inttostr(nSpellPoint));
if (nSpellPoint > 0) and (nSpellPoint <= m_WAbil.MP) then Result := True;
end;
end else begin
Result := (UserMagic.btKey > 0) or m_boAI ;
end;
end;

end;
function TAIPlayObject.GetAttackDir(BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean;
var
nX, nY: Integer;
begin
Result := False;
btDir := GetNextDirection(m_nCurrX, m_nCurrY, BaseObject.m_nCurrX, BaseObject.m_nCurrY);
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, btDir, nRange, nX, nY) then begin
Result := BaseObject = TBaseObject(m_PEnvir.GetMovingObject(nX, nY, BaseObject, True));
end;
end;

function TAIPlayObject.SelectMagic(): Integer;

function SelKTZandCID(var nSelectMagic: Integer): Boolean;
var
boKTZHitSkill, boCIDHitSkill: Boolean;
begin
Result := False;
boKTZHitSkill := False;

if AllowUseMagic(43) then begin
boKTZHitSkill := True;
end;

if boKTZHitSkill then begin
//Randomize;
nSelectMagic := 43;
Result := True;
Exit;
end;

end;

 

function GetSlaveCount: Integer;
var
I: Integer;
BaseObject: TBaseObject;
begin
Result := 0;
if m_SlaveList.Count <= 0 then Exit;
for I := 0 to m_SlaveList.Count - 1 do begin
BaseObject := m_SlaveList.Items[I];
if (not BaseObject.m_boDeath) and (not BaseObject.m_boGhost) {and (BaseObject.m_nCopyHumanLevel = 0)} then Inc(Result);
end;
end;

 

var
wHitMode: Word;
btDir: Byte;
nSelectMagic: Integer;
UserMagic: pTUserMagic;
nRangeTargetCount: Integer;
nSelfRangeTargetCount: Integer;
nRangeTargetCountByDir: Integer;
boVisibleActors: Boolean;
nStep: Integer;
nItemCount,II, nCode: Integer;
StdItem :tStdItem;
UserItem:ptUserItem;
begin
Result := 0;
case m_btJob of
0: begin //战士

if m_boFireHitSkill then begin
Result := 26;
Exit;
end;

 

if AllowUseMagic(26) and (not m_boFireHitSkill) and ((GetTickCount - m_dwLatestFireHitTick) > 10 * 1000) then begin {烈火}
AllowFireHitSkill;
Result := 26;
Exit;
end;

if SelKTZandCID(nSelectMagic) then begin
Result := nSelectMagic;
Exit;
end;

 

nRangeTargetCount := GetNearTargetCount;

if (nRangeTargetCount >= 2) then begin //被怪物包围 >=2
if AllowUseMagic(25) then begin //半月
if not m_boUseHalfMoon then begin
HalfMoonOnOff(True);
end;
Result := 25;
Exit;
end;
end;

if (Random(10) = 0) and AllowUseMagic(7) then begin //英雄攻杀剑术
m_boPowerHit := True;
Result := 7;
Exit;
end;

if AllowUseMagic(12) then begin //英雄刺杀剑术
if not m_boUseThrusting then begin
ThrustingOnOff(True);
end;
Result := 12;
Exit;
end;

if AllowUseMagic(25) then begin //半月
if not m_boUseHalfMoon then begin
HalfMoonOnOff(True);
end;
Result := 25;
Exit;
end;

if AllowUseMagic(40) then begin //英雄抱月刀法
if not m_boCrsHitkill then begin
SkillCrsOnOff(True);
end;
Result := 40;
Exit;
end;

if (m_TargetCret <> nil) and (not m_TargetCret.m_boDeath) and AllowUseMagic(7) then begin //英雄攻杀剑术
Result := 7;
Exit;
end;

if SelKTZandCID(nSelectMagic) then begin
Result := nSelectMagic;
Exit;
end;
end;
1: begin //法师
if (AllowUseMagic(31)) and (m_wStatusTimeArr[STATE_BUBBLEDEFENCEUP {0x76}] = 0) then begin {使用 魔法盾}
Result := 31;
Exit;
end;
nRangeTargetCount := GetRangeTargetCount(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, 3);
nSelfRangeTargetCount := GetNearTargetCount;

 

if (m_TargetCret <> nil) and (not m_TargetCret.m_boDeath) and AllowUseMagic(11) and ((GetTickCount -m_SkillUseTick[11])>900)then begin
m_SkillUseTick[11]:= GetTickCount;
Result := 11; //雷电术
Exit;
end;
if (m_TargetCret <> nil) and (not m_TargetCret.m_boDeath) and AllowUseMagic(5) then begin
Result := 5; //大火球
Exit;
end;
if (m_TargetCret <> nil) and (not m_TargetCret.m_boDeath) and AllowUseMagic(1) then begin
Result := 1; //火球术
Exit;
end;

if AllowUseMagic(37) then begin
Result := 37; //群体雷电术
Exit;
end;
if AllowUseMagic(23) then begin
Result := 23; //爆裂火焰
Exit;
end;
if AllowUseMagic(33) then begin
Result := 33; //冰咆哮
Exit;
end;
if AllowUseMagic(45) then begin
Result := 45; //灭天火
Exit;
end;
if AllowUseMagic(47) then begin
Result := 47; //火龙焰
Exit;
end;

end;
2: begin //道士
nCode := 0;
try

//try
if m_WAbil.HP <= m_WAbil.MaxHP * 80 div 100 then begin
// m_wLastHP := m_WAbil.HP;
if GetTickCount - m_SkillUseTick[29] > 1000 * 5 then begin
if m_nIncSelfHealthCount <= 3 then begin
if AllowUseMagic(2) and AllowUseMagic(29) then begin
nCode := 9;
begin
m_boSelSelf := True;
Inc(m_nIncSelfHealthCount);
Result := 2;
end;
Exit;
end;
nCode := 10;
if AllowUseMagic(29) then begin {使用群体治愈术}
m_boSelSelf := True;
Inc(m_nIncSelfHealthCount);
Result := 29;
Exit;
end;
nCode := 11;
if AllowUseMagic(2) then begin {使用治愈术}
m_boSelSelf := True;
Inc(m_nIncSelfHealthCount);
Result := 2;
Exit;
end;
end else begin
m_SkillUseTick[29] := GetTickCount;
m_nIncSelfHealthCount := 0;
end;
end;
end;

 

nCode := 1;
//IF m_TargetCret <> nil then
nRangeTargetCount := GetRangeTargetCount(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, 3);
nCode := 2;
nSelfRangeTargetCount := GetNearTargetCount;
nCode := 3;

if AllowUseMagic(30) and (GetSlaveCount <= 0) and (GetTickCount - m_SkillUseTick[30] > 1000 * 5) then begin
m_SkillUseTick[30] := GetTickCount;
Result := 30; //召唤神兽
Exit;
end;
nCode := 5;
if AllowUseMagic(17) and (GetSlaveCount <= 0) and (GetTickCount - m_SkillUseTick[17] > 1000 * 7) then begin
m_SkillUseTick[17] := GetTickCount;
Result := 17; //召唤神兽
Exit;
end;
nCode := 6;

 

{ nCode := 17;
if AllowUseMagic(15) and (m_wStatusTimeArr[STATE_DEFENCEUP] <10) then begin // 使用神圣战甲术
MainOutMessage('圣神:'+inttostr(m_wStatusTimeArr[STATE_DEFENCEUP]));
Result := 15;
Exit;
end;
nCode := 18;
if AllowUseMagic(14) and (m_wStatusTimeArr[STATE_MAGDEFENCEUP] <10) then begin // 幽灵盾

Result := 14;
Exit;
end;
}

if (m_TargetCret <> nil) and (not m_TargetCret.m_boDeath)and ((GetTickCount -m_SkillUseTick[11])>900) then begin
m_SkillUseTick[11]:= GetTickCount;
if AllowUseMagic(13) then begin //灵魂火符
Result := 13;
Exit;
end;
end;

except
MainOutMessage('SelMagic:'+m_sCharName+inttostr(nCode));
end;
end;
end;
end;
function TAIPlayObject.CanLineAttack(nCurrX, nCurrY: Integer): Boolean; //目标是否和自己在一条线上,用来检测直线攻击的魔法是否可以攻击到目标
var
I: Integer;
btDir: Byte;
nX, nY: Integer;
begin
Result := False;
nX := nCurrX;
nY := nCurrY;
btDir := GetNextDirection(nCurrX, nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
while True do begin
if (m_TargetCret.m_nCurrX = nX) and (m_TargetCret.m_nCurrY = nY) then begin
Result := True;
Break;
end;
btDir := GetNextDirection(nX, nY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
if not m_PEnvir.GetNextPosition(nX, nY, btDir, 1, nX, nY) then Break;
if not m_PEnvir.CanWalkEx(nX, nY, True) then Break;
end;
end;

function TAIPlayObject.CanLineAttack(nStep: Integer): Boolean;
var
I: Integer;
btDir: Byte;
nX, nY: Integer;
begin
Result := False;
nX := m_nCurrX;
nY := m_nCurrY;
btDir := GetNextDirection(nX, nY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
for I := 1 to nStep do begin
if (m_TargetCret.m_nCurrX = nX) and (m_TargetCret.m_nCurrY = nY) then begin
Result := True;
Break;
end;
btDir := GetNextDirection(nX, nY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
if not m_PEnvir.GetNextPosition(nX, nY, btDir, 1, nX, nY) then Break;
if not m_PEnvir.CanWalkEx(nX, nY, True) then Break;
end;
end;
function TAIPlayObject.GotoNextOne(nX, nY: Integer; boRun: Boolean): Boolean;
var
I, nStep: Integer;
Path: TPath;
begin
Result := False;
if (abs(nX - m_nCurrX) <= 2) and (abs(nY - m_nCurrY) <= 2) then begin
if (abs(nX - m_nCurrX) <= 1) and (abs(nY - m_nCurrY) <= 1) then begin
Result := WalkToNext(nX, nY);
end else begin
Result := RunToNext(nX, nY);
end;
end;

if not Result then begin
g_FindPath.BaseObject := Self;
Path := g_FindPath.FindPath(m_PEnvir, m_nCurrX, m_nCurrY, nX, nY, boRun, False);
//MainOutMessage(Format('%s TAIObject.GotoNextOne:(%d)', [m_sCharName, Length(Path)]));
if Length(Path) > 0 then begin
for I := 0 to Length(Path) - 1 do begin
if (Path[I].X <> m_nCurrX) or (Path[I].Y <> m_nCurrY) then begin
if (abs(Path[I].X - m_nCurrX) >= 2) or (abs(Path[I].Y - m_nCurrY) >= 2) then begin
Result := RunToNext(Path[I].X, Path[I].Y);
end else begin
Result := WalkToNext(Path[I].X, Path[I].Y);
end;
break;
end;
end;
Path := nil;
end;
end;
m_RunPos.nAttackCount := 0;
end;

function TAIPlayObject.RunToNext(nX, nY: Integer): Boolean;
begin
Result := RunTo(GetNextDirection(m_nCurrX, m_nCurrY, nX, nY), False, nX, nY);
end;

function TAIPlayObject.WalkToNext(nX, nY: Integer): Boolean;
begin
Result := WalkTo(GetNextDirection(m_nCurrX, m_nCurrY, nX, nY), False);
end;

function TAIPlayObject.GotoNext(nX, nY: Integer; boRun: Boolean): Boolean;
var
I, nStep: Integer;
Path: TPath;
begin
Result := False;
nStep := 0;
if (abs(nX - m_nCurrX) <= 2) and (abs(nY - m_nCurrY) <= 2) then begin
if (abs(nX - m_nCurrX) <= 1) and (abs(nY - m_nCurrY) <= 1) then begin
Result := WalkToNext(nX, nY);
end else begin
Result := RunToNext(nX, nY);
end;
nStep := 1;
end;

if not Result then begin
g_FindPath.BaseObject := Self;
Path := g_FindPath.FindPath(m_PEnvir, m_nCurrX, m_nCurrY, nX, nY, boRun, False);
//Path := FindWalkPath(m_nCurrX, m_nCurrY, nX, nY, boRun, False);
if Length(Path) > 0 then begin
for I := 0 to Length(Path) - 1 do begin
if (Path[I].X <> m_nCurrX) or (Path[I].Y <> m_nCurrY) then begin
if (abs(Path[I].X - m_nCurrX) >= 2) or (abs(Path[I].Y - m_nCurrY) >= 2) then begin
Result := RunToNext(Path[I].X, Path[I].Y);
end else begin
Result := WalkToNext(Path[I].X, Path[I].Y);
end;
if Result then Inc(nStep) else break;
if nStep >= 3 then break;
end;
end;
Path := nil;
end;
end;
m_RunPos.nAttackCount := 0;
end;

function TAIPlayObject.CanWalk(nCurrX, nCurrY, nTargetX, nTargetY: Integer; nDir: Integer; var nStep: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;
nX, nY, nCount: Integer;
begin
Result := False;
nStep := 0;
nCount := 0;
if (nDir >= 0) and (nDir <= 7) then btDir := nDir
else btDir := GetNextDirection(nCurrX, nCurrY, nTargetX, nTargetY);
{nX := nCurrX;
nY := nCurrY;}
if boFlag then begin
if (abs(nCurrX - nTargetX) <= 1) and (abs(nCurrY - nTargetY) <= 1) then begin
if m_PEnvir.GetNextPosition(nCurrX, nCurrY, btDir, 1, nX, nY) and (nX = nTargetX) and (nY = nTargetY) then begin
nStep := 1;
Result := True;
end;
end else begin
if m_PEnvir.GetNextPosition(nCurrX, nCurrY, btDir, 2, nX, nY) and (nX = nTargetX) and (nY = nTargetY) then begin
nStep := 1;
Result := True;
end;
end;
end else begin
if m_PEnvir.GetNextPosition(nCurrX, nCurrY, btDir, 1, nX, nY) and (nX = nTargetX) and (nY = nTargetY) then begin
nStep := nStep + 1;
Result := True;
Exit;
end else Exit;
if m_PEnvir.GetNextPosition(nX, nY, btDir, 1, nX, nY) and (nX = nTargetX) and (nY = nTargetY) then begin
nStep := nStep + 1;
Result := True;
Exit;
end;
end;
{while True do begin
if (nX = nTargetX) and (nY = nTargetY) then Break;
if GetNextDirection(nX, nY, nTargetX, nTargetY) <> btDir then Break;
if m_PEnvir.GetNextPosition(nX, nY, btDir, 1, nX, nY) then begin
if (not m_PEnvir.CanWalkEx(nX, nY, boFlag)) or (not m_PEnvir.CanWalkOfEvent(Self, nX, nY)) then begin
Result := False;
Break;
end;
Inc(nStep);
end else begin
Result := False;
Break;
end;
Inc(nCount);
end;}
end;
function TAIPlayObject.GetMasterRange(nTargetX, nTargetY: Integer): Integer;
var
nCurrX, nCurrY: Integer;
begin
Result := 0;
end;
function TAIPlayObject.IsGotoXY(X1, Y1, X2, Y2: Integer): Boolean;
var
I, nStep: Integer;
Path: TPath;
begin
Result := False;
if (not CanWalk(X1, Y1, X2, Y2, -1, nStep, true)) then begin
g_FindPath.BaseObject := Self;
Path := g_FindPath.FindPath(m_PEnvir, X1, Y1, X2, Y2, False, False);
if Length(Path) <= 0 then Exit;
Path := nil;
Result := True;
end else Result := True;
end;

 

function TAIPlayObject.ActThink(wMagicID: Word): Boolean;

function FindGoodPathA(WalkStep: TWalkStep; nRange, nType: Integer): TMapWalkXY;
var
I: Integer;
n10: Integer;
n1C: Integer;
nMastrRange: Integer;
nMonCount: Integer;
MapWalkXY, MapWalkXYA: pTMapWalkXY;
begin
n10 := High(Integer);
MapWalkXY := nil;
FillChar(Result, SizeOf(TMapWalkXY), 0);

for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) and
(abs(WalkStep[I].nX - m_TargetCret.m_nCurrX) >= nRange) and (abs(WalkStep[I].nY - m_TargetCret.m_nCurrY) >= nRange) then begin
if (WalkStep[I].nMonCount < n10) then begin
n10 := WalkStep[I].nMonCount;
MapWalkXY := @WalkStep[I];
end;
end;
end;

if (MapWalkXY <> nil) and (m_Master <> nil) then begin
nMonCount := MapWalkXY.nMonCount;
nMastrRange := MapWalkXY.nMastrRange;
n10 := High(Integer);
MapWalkXYA := MapWalkXY;
MapWalkXY := nil;
for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) and (WalkStep[I].nMonCount <= nMonCount) and (abs(WalkStep[I].nX - m_TargetCret.m_nCurrX) >= nRange) and (abs(WalkStep[I].nY - m_TargetCret.m_nCurrY) >= nRange) then begin
if (WalkStep[I].nMastrRange < n10) and (WalkStep[I].nMastrRange < nMastrRange) then begin
n10 := WalkStep[I].nMastrRange;
MapWalkXY := @WalkStep[I];
end;
end;
end;
if MapWalkXY = nil then MapWalkXY := MapWalkXYA;
end;

{if nType <> 0 then begin
if MapWalkXY <> nil then begin
nMonCount := MapWalkXY.nMonCount;
n10 := High(Integer);
MapWalkXY := nil;
for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) and (WalkStep[I].nMonCount <= nMonCount) and

(abs(WalkStep[I].nX - m_TargetCret.m_nCurrX) >= nRange) and
(abs(WalkStep[I].nY - m_TargetCret.m_nCurrY) >= nRange) then begin
if (WalkStep[I].nMastrRange < n10) then begin
n10 := WalkStep[I].nMastrRange;
MapWalkXY := @WalkStep[I];
end;
end;
end;
end;
end; }
if MapWalkXY <> nil then Result := MapWalkXY^;
end;

function FindGoodPathB(WalkStep: TWalkStep; nType: Integer): TMapWalkXY;
var
I: Integer;
n10: Integer;
n1C: Integer;
nMastrRange: Integer;
nMonCount: Integer;
MapWalkXY, MapWalkXYA: pTMapWalkXY;
begin
n10 := High(Integer);
MapWalkXY := nil;
FillChar(Result, SizeOf(TMapWalkXY), 0);

for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) then begin
if (WalkStep[I].nMonCount < n10) then begin
n10 := WalkStep[I].nMonCount;
MapWalkXY := @WalkStep[I];
end;
end;
end;

if (MapWalkXY <> nil) and (m_Master <> nil) then begin
nMonCount := MapWalkXY.nMonCount;
nMastrRange := MapWalkXY.nMastrRange;
n10 := High(Integer);
MapWalkXYA := MapWalkXY;
MapWalkXY := nil;
for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) and (WalkStep[I].nMonCount <= nMonCount) then begin
if (WalkStep[I].nMastrRange < n10) and (WalkStep[I].nMastrRange < nMastrRange) then begin
n10 := WalkStep[I].nMastrRange;
MapWalkXY := @WalkStep[I];
end;
end;
end;
if MapWalkXY = nil then MapWalkXY := MapWalkXYA;
end;

 

if MapWalkXY <> nil then Result := MapWalkXY^;
end;

function FindMinRange(WalkStep: TWalkStep): TMapWalkXY;
var
I: Integer;
n10: Integer;
n1C: Integer;
n2C: Integer;
nMonCount: Integer;
MapWalkXY, MapWalkXYA: pTMapWalkXY;
begin
n10 := High(Integer);
n1C := 0;
MapWalkXY := nil;
FillChar(Result, SizeOf(TMapWalkXY), 0);

for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) then begin
n1C := abs(WalkStep[I].nX - m_TargetCret.m_nCurrX) + abs(WalkStep[I].nY - m_TargetCret.m_nCurrY);
if (n1C < n10) then begin
n10 := n1C;
MapWalkXY := @WalkStep[I];
end;
end;
end;

if MapWalkXY <> nil then begin
nMonCount := MapWalkXY.nMonCount;
MapWalkXYA := MapWalkXY;
MapWalkXY := nil;
for I := DR_UP to DR_UPLEFT do begin
if (WalkStep[I].nWalkStep > 0) and (WalkStep[I].nMonCount <= nMonCount) then begin
n1C := abs(WalkStep[I].nX - m_TargetCret.m_nCurrX) + abs(WalkStep[I].nY - m_TargetCret.m_nCurrY);
if (n1C <= n10) then begin
n10 := n1C;
MapWalkXY := @WalkStep[I];
end;
end;
end;
if MapWalkXY = nil then MapWalkXY := MapWalkXYA;
end;

if MapWalkXY <> nil then Result := MapWalkXY^;
end;

function CanWalkNextPosition(nX, nY, nRange: Integer; btDir: Byte; boFlag: Boolean): Boolean; //检测下一步在不在攻击位
var
nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;
if m_PEnvir.GetNextPosition(nX, nY, btDir, 1, nCurrX, nCurrY) and
CanMove(nX, nY, nCurrX, nCurrY, False) and
(not boFlag) then begin
Result := True;
Exit;
end;

if m_PEnvir.GetNextPosition(nX, nY, btDir, 2, nCurrX, nCurrY) and
CanMove(nX, nY, nCurrX, nCurrY, False) and
(not boFlag) then begin
Result := True;
Exit;
end;
end;

function FindPosOfSelf(WalkStep: pTWalkStep; nRange: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;

nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, nRange, nCurrX, nCurrY) and CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
end;

function _FindPosOfSelf(WalkStep: pTWalkStep; nRange: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;

nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, nRange, nCurrX, nCurrY) and CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) or CanWalkNextPosition(nCurrX, nCurrY, nRange, I, boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
end;

function FindPosOfTarget(WalkStep: pTWalkStep; nTargetX, nTargetY, nRange: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;
nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;
FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(nTargetX, nTargetY, I, nRange, nCurrX, nCurrY) and
m_PEnvir.CanWalkEx(nCurrX, nCurrY, False)
then begin
if ((not boFlag) ) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - nTargetX) + abs(nCurrY - nTargetY);

WalkStep[I].nMonCount := GetRangeTargetCount(nCurrX, nCurrY, 2); //GetNearTargetCount(nCurrX, nCurrY);
Result := True;
end;
end;
end;
end;

function FindPos(WalkStep: pTWalkStep; nRange: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;

nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, 2, nCurrX, nCurrY) and CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
if Result then Exit;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, 1, nCurrX, nCurrY) and CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
end;

function _FindPos(WalkStep: pTWalkStep; nRange: Integer; boFlag: Boolean): Boolean;
var
I: Integer;
btDir: Byte;

nCurrX: Integer;
nCurrY: Integer;
begin
Result := False;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, 1, nCurrX, nCurrY) and CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) or CanWalkNextPosition(nCurrX, nCurrY, nRange, I, boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
if Result then Exit;

FillChar(WalkStep^, SizeOf(TMapWalkXY) * 8, 0);
for I := DR_UP to DR_UPLEFT do begin
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, I, 2, nCurrX, nCurrY) and
CanMove(nCurrX, nCurrY, False) then begin
if (not boFlag) or CanWalkNextPosition(nCurrX, nCurrY, nRange, I, boFlag) then begin
WalkStep[I].nWalkStep := nRange;
WalkStep[I].nX := nCurrX;
WalkStep[I].nY := nCurrY;
WalkStep[I].nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
WalkStep[I].nMonCount := GetNearTargetCount(nCurrX, nCurrY);

Result := True;
end;
end;
end;
end;

function WalkToRightPos(): Boolean;
var
I: Integer;
boFlag: Boolean;
nRange: Integer;
btDir: Byte;
WalkStep: TWalkStep;
MapWalkXY: TMapWalkXY;
nError: Integer;
begin
Result := False;
try
nError := 0;
boFlag := (m_btRaceServer = RC_PLAYOBJECT) or (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2, SKILL_FIRECHARM]) or (m_btJob = 0);
if (m_btJob = 0) or (wMagicID <= 0) then begin
nRange := 1;
if (wMagicID = 58) or (wMagicID = 77) then nRange := 4;
if (wMagicID = 12) then nRange := 2;
if (wMagicID in [60, 61, 62]) then nRange := 6;
nError := 1;

nError := 24;
for I := nRange downto 1 do begin
nError := 25;
if FindPosOfTarget(@WalkStep, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, I, boFlag) then begin
nError := 26;
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin
MapWalkXY := FindGoodPathB(WalkStep, 0);
end;}
MapWalkXY := FindGoodPathB(WalkStep, 0);
nError := 27;
if (MapWalkXY.nWalkStep > 0) then begin
nError := 28;
//if m_btRaceServer <> RC_MOONOBJECT then begin
if GotoNext(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
nError := 29;
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
{end else begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_MOONOBJECT) then begin
nError := 29;
m_RunPos.btDirection := 0;
Result := True;
break;
end;
end;}
end;
end;
end;

nError := 12;
for I := 2 downto 1 do begin
nError := 13;
if FindPosOfSelf(@WalkStep, I, boFlag) then begin
nError := 14;
if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin
MapWalkXY := FindGoodPathB(WalkStep, 0);
end;
nError := 15;
if (MapWalkXY.nWalkStep > 0) then begin
nError := 16;
if GotoNext(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
nError := 17;
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;
end else begin
if wMagicID > 0 then
nRange := _MAX(Random(3), 2)
else
nRange := 1;

//boFlag := nRange = 1;
boFlag := (m_btRaceServer = RC_PLAYOBJECT) or (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2, SKILL_FIRECHARM]) or (nRange = 1);

for I := 2 downto 1 do begin
if FindPosOfSelf(@WalkStep, I, boFlag) then begin
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathA(WalkStep, nRange, 1);
end else begin
MapWalkXY := FindGoodPathA(WalkStep, nRange, 0);
end;}
MapWalkXY := FindGoodPathA(WalkStep, nRange, 0);
if (MapWalkXY.nWalkStep > 0) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;

for I := 2 downto 1 do begin
if _FindPosOfSelf(@WalkStep, I, boFlag) then begin
MapWalkXY := FindMinRange(WalkStep);
if (MapWalkXY.nWalkStep > 0) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;

for I := nRange downto 1 do begin
if FindPosOfTarget(@WalkStep, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, I, boFlag) then begin
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin
MapWalkXY := FindGoodPathB(WalkStep, 0);
end; }
MapWalkXY := FindGoodPathB(WalkStep, 0);
if (MapWalkXY.nWalkStep > 0) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;
end;
except
MainOutMessage('WalkToRightPos:' + m_sCharName + ' ' + IntToStr(nError));
end;
end;

function AvoidTarget: Boolean;
var
I, II: Integer;
nRange: Integer;
btDir: Byte;
nX, nY: Integer;
boFlag: Boolean;
WalkStep: TWalkStep;
MapWalkXY: TMapWalkXY;
begin
Result := False;
nRange := _MAX(Random(3), 2);

boFlag := (m_btRaceServer = RC_PLAYOBJECT) or (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2, SKILL_FIRECHARM]);
for I := nRange downto 1 do begin
//if FindPosOfTarget(@WalkStep, ActorObject.m_nCurrX, ActorObject.m_nCurrY, I, boFlag) then begin
if FindPosOfSelf(@WalkStep, I, boFlag) then begin
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin
MapWalkXY := FindGoodPathB(WalkStep, 0);
end;}
MapWalkXY := FindGoodPathB(WalkStep, 0);
if (MapWalkXY.nWalkStep > 0) then begin
btDir := GetNextDirection(m_nCurrX, m_nCurrY, MapWalkXY.nX, MapWalkXY.nY);
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
if (m_btRaceServer <> RC_PLAYOBJECT) then begin
for II := nRange downto 1 do begin //再跑1次
if m_PEnvir.GetNextPosition(MapWalkXY.nX, MapWalkXY.nY, btDir, II, nX, nY) and m_PEnvir.CanWalkEx(nX, nY, True) and
(GetNearTargetCount(nX, nY) <= MapWalkXY.nMonCount) then begin
GotoNextOne(nX, nY, m_btRaceServer <> RC_PLAYOBJECT);
break;
end;
end;
end;
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;

for I := nRange downto 1 do begin
//if FindPosOfTarget(@WalkStep, ActorObject.m_nCurrX, ActorObject.m_nCurrY, I, boFlag) then begin
if _FindPosOfSelf(@WalkStep, I, boFlag) then begin
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin
MapWalkXY := FindGoodPathB(WalkStep, 0);
end;}
MapWalkXY := FindGoodPathB(WalkStep, 0);
if (MapWalkXY.nWalkStep > 0) then begin
btDir := GetNextDirection(m_nCurrX, m_nCurrY, MapWalkXY.nX, MapWalkXY.nY);
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
for II := nRange downto 1 do begin //再跑1次
if m_PEnvir.GetNextPosition(MapWalkXY.nX, MapWalkXY.nY, btDir, II, nX, nY) and m_PEnvir.CanWalkEx(nX, nY, True) and
(GetNearTargetCount(nX, nY) <= MapWalkXY.nMonCount) then begin
MapWalkXY.nX := nX;
MapWalkXY.nY := nY;
GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT);
break;
end;
end;
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;
end;

function FollowTarget: Boolean;
var
I: Integer;
nRange: Integer;
boFlag: Boolean;
WalkStep: TWalkStep;
MapWalkXY: TMapWalkXY;
begin
Result := False;
nRange := 2;
boFlag := (m_btRaceServer = RC_PLAYOBJECT) or (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2, SKILL_FIRECHARM]);
for I := nRange downto 1 do begin
if FindPosOfSelf(@WalkStep, I, boFlag) then begin
{if m_Master <> nil then begin
MapWalkXY := FindGoodPathB(WalkStep, 1);
end else begin inner power
MapWalkXY := FindGoodPathB(WalkStep, 0);
end;}
MapWalkXY := FindMinRange(WalkStep);

if (MapWalkXY.nWalkStep > 0) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;

for I := nRange downto 1 do begin
if _FindPosOfSelf(@WalkStep, I, boFlag) then begin
MapWalkXY := FindMinRange(WalkStep);
if (MapWalkXY.nWalkStep > 0) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
m_RunPos.btDirection := 0;
Result := True;
Exit;
end;
end;
end;
end;
end;

function MotaeboPos(): Boolean; //获取野蛮冲撞
var
nTargetX, nTargetY: Integer;
btNewDir: Byte;
begin
Result := False;
if (m_TargetCret = nil) or (m_Master = nil) then Exit;

if (GetPoseCreate = m_TargetCret) or (m_TargetCret.GetPoseCreate = Self) then begin
btNewDir := GetNextDirection(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
if m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, btNewDir, 1, nTargetX, nTargetY) then begin
if m_PEnvir.CanWalk(nTargetX, nTargetY, True) then begin
Result := True;
Exit;
end;
end;
end;
Result := WalkToRightPos;
end;

function FindPosOfDir(nDir, nRange: Integer; boFlag: Boolean): TMapWalkXY;
var
I: Integer;
btDir: Byte;

nCurrX: Integer;
nCurrY: Integer;
begin
FillChar(Result, SizeOf(TMapWalkXY), 0);
if m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, nDir, nRange, nCurrX, nCurrY) and
CanMove(nCurrX, nCurrY, False) and ((boFlag and CanLineAttack(nCurrX, nCurrY)) or (not boFlag)) then begin
Result.nWalkStep := nRange;
Result.nX := nCurrX;
Result.nY := nCurrY;
Result.nMonRange := abs(nCurrX - m_TargetCret.m_nCurrX) + abs(nCurrY - m_TargetCret.m_nCurrY);
Result.nMonCount := GetNearTargetCount(nCurrX, nCurrY);

end;
end;

function RunPosAttack(): Boolean;
function GetNextRunPos(btDir: Byte; boTurn: Boolean): Byte;
begin
if boTurn then begin
case btDir of
DR_UP: Result := DR_RIGHT;
DR_UPRIGHT: Result := DR_DOWNRIGHT;
DR_RIGHT: Result := DR_DOWN;
DR_DOWNRIGHT: Result := DR_DOWNLEFT;
DR_DOWN: Result := DR_LEFT;
DR_DOWNLEFT: Result := DR_UPLEFT;
DR_LEFT: Result := DR_UP;
DR_UPLEFT: Result := DR_UPRIGHT;
end;
end else begin
case btDir of
DR_UP: Result := DR_LEFT;
DR_UPRIGHT: Result := DR_UPLEFT;
DR_RIGHT: Result := DR_UP;
DR_DOWNRIGHT: Result := DR_UPRIGHT;
DR_DOWN: Result := DR_RIGHT;
DR_DOWNLEFT: Result := DR_DOWNRIGHT;
DR_LEFT: Result := DR_DOWN;
DR_UPLEFT: Result := DR_DOWNLEFT;
end;
end;
end;
var
WalkStep: array[0..1] of TMapWalkXY;
MapWalkXY: pTMapWalkXY;
btNewDir1: Byte;
btNewDir2: Byte;
nRange: Integer;
boFlag: Boolean;
btDir: Byte;
nNearTargetCount: Integer;
begin
Result := False;

btDir := GetNextDirection(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);

btNewDir1 := GetNextRunPos(btDir, True);
btNewDir2 := GetNextRunPos(btDir, False);
FillChar(WalkStep, SizeOf(TMapWalkXY) * 2, 0);

 

 

 

if m_btJob = 0 then begin
nRange := 1;
if (wMagicID = 58) or (wMagicID = 77) then nRange := 2;
if (wMagicID = 12) then nRange := 2;
if (wMagicID in [60, 61, 62]) then nRange := 6;
//nRange := 2;
WalkStep[0] := FindPosOfDir(btNewDir1, nRange, True);
WalkStep[1] := FindPosOfDir(btNewDir2, nRange, True);
end else begin
//nRange := GetStep(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
nRange := 2;
boFlag := False; // (m_btRaceServer = RC_MOONOBJECT) or (wMagicID in [SKILL_FIREBALL, SKILL_FIREBALL2, SKILL_FIRECHARM]);
WalkStep[0] := FindPosOfDir(btNewDir1, nRange, boFlag);
WalkStep[1] := FindPosOfDir(btNewDir2, nRange, boFlag);
end;

nNearTargetCount := GetNearTargetCount(m_nCurrX, m_nCurrY);
MapWalkXY := nil;
if (WalkStep[0].nWalkStep > 0) and (WalkStep[1].nWalkStep > 0) then begin
if m_RunPos.btDirection > 0 then begin
MapWalkXY := @WalkStep[1];
end else begin
MapWalkXY := @WalkStep[0];
end;
if (nNearTargetCount < WalkStep[0].nMonCount) and (nNearTargetCount < WalkStep[1].nMonCount) then
MapWalkXY := nil
else
if (m_RunPos.btDirection > 0) and (nNearTargetCount < WalkStep[1].nMonCount) then
MapWalkXY := nil
else
if (m_RunPos.btDirection <= 0) and (nNearTargetCount < WalkStep[0].nMonCount) then
MapWalkXY := nil;

if (nNearTargetCount > 0) and (MapWalkXY <> nil) and (MapWalkXY.nMonCount > nNearTargetCount) then
MapWalkXY := nil;
end else
if (WalkStep[0].nWalkStep > 0) then begin
MapWalkXY := @WalkStep[0];
if (nNearTargetCount < WalkStep[0].nMonCount) then
MapWalkXY := nil;
m_RunPos.btDirection := 0;
end else
if (WalkStep[1].nWalkStep > 0) then begin
MapWalkXY := @WalkStep[1];
if (nNearTargetCount < WalkStep[1].nMonCount) then
MapWalkXY := nil;
m_RunPos.btDirection := 1;
end;
if (MapWalkXY <> nil) then begin
if GotoNextOne(MapWalkXY.nX, MapWalkXY.nY, m_btRaceServer <> RC_PLAYOBJECT) then begin
Result := True;
end;
end;
if not Result then begin
m_RunPos.nAttackCount := 0;
end;
end;
var
nCode, nError, nThinkCount: Integer;
begin
Result := False;
nError := 0;
nThinkCount := 0;
try
while True do begin
if m_TargetCret = nil then break;
nThinkCount := nThinkCount + 1;
nCode := DoThink(wMagicID);
nError := 1;
//if m_btRaceServer = RC_HEROOBJECT then
//MainOutMessage('nCode:' + m_TargetCret.m_sCharName + ' ' + IntToStr(nCode) + ' ' + IntToStr(Integer(m_TargetCret)));
case m_btJob of
0: begin
case nCode of
2: begin
nError := 2;
if WalkToRightPos then begin
Result := True;
//MainOutMessage('WalkToRightPos:' + m_TargetCret.m_sCharName + ' ' + IntToStr(nCode) + ' ' + IntToStr(Integer(m_TargetCret)));
end else begin //无法走到正确的攻击坐标
//MainOutMessage('WalkToRightPos=FALSE:' + m_TargetCret.m_sCharName + ' ' + IntToStr(nCode) + ' ' + IntToStr(Integer(m_TargetCret)));
nError := 3;
DelTargetCreat;
if nThinkCount < 2 then begin
nError := 4;
//SearchTargetxy;
nError := 5;
Continue;
end;
end;
end;
5: begin
nError := 6;
if RunPosAttack then begin
Result := True;
end;
nError := 7;
end;
end;
end;
1, 2: begin
case nCode of
1: begin
nError := 8;
Result := AvoidTarget;
nError := 9;
end;
2: begin
nError := 10;
if FollowTarget then begin
nError := 11;
Result := True;
end else begin //无法走到正确的攻击坐标
nError := 12;
DelTargetCreat;
nError := 13;
if nThinkCount < 2 then begin
nError := 14;
// SearchTargetxy;
nError := 15;
Continue;
end;
end;
end;
3, 4: begin
nError := 16;
if WalkToRightPos then begin
Result := True;
end else begin //无法走到正确的攻击坐标
nError := 3;
DelTargetCreat;
if nThinkCount < 2 then begin
nError := 4;
// SearchTargetxy;
nError := 5;
Continue;
end;
end;
//Result := AvoidTarget;
nError := 17;
end;

5: begin
nError := 24;
Result := RunPosAttack;
nError := 25;
end;
end;
end;
end;
break;
end;
except
MainOutMessage('TAIObject::ActThink Error:' + m_sCharName + ' Code:' + IntToStr(nCode) + ' Error:' + IntToStr(nError));
end;
end;

function TAIPlayObject.Operate(ProcessMsg: pTProcessMessage): Boolean;
begin
Result := inherited Operate(ProcessMsg);
end;

 

 

 

 

 

 

 

function TAIPlayObject.StartAttack(wMagIdx: Integer): Boolean;
var
nDir:byte;
resourcestring
sExceptionMsg = '[Exception] TAIObject::StartAttack Race=%d MagIdx=%d';

begin
Result := False;
try
m_dwTargetFocusTick := GetTickCount();

 

 

 

//MainOutMessage(Format('%s TAIObject.StartAttack %d', [m_sCharName, wMagIdx]));
case m_btJob of
0: begin
Result := WarrorAttackTarget(wMagIdx);
end;
1: begin
Result := WizardAttackTarget(wMagIdx);
end;
2: begin
Result := TaoistAttackTarget(wMagIdx);
end;
end;

except
MainOutMessage(Format(sExceptionMsg, [m_btRaceServer, wMagIdx]));
end;
end;

function TAIPlayObject.Think: Boolean;
var
nOldX, nOldY : integer;
begin
Result := False;
if m_boMissionKz then
Exit;
if (GetTickCount - m_dwThinkTick) > 3 * 1000 then
begin
m_dwThinkTick := GetTickCount();
if m_PEnvir.GetXYObjCount(m_nCurrX, m_nCurrY) >= 2 then
m_boDupMode := True;
if not IsProperTarget {FFFF4}(m_TargetCret) then
m_TargetCret := nil;
end; //004A8ED2
if m_boDupMode then
begin //人物重叠了
nOldX := m_nCurrX;
nOldY := m_nCurrY;
WalkTo(Random(8), False);
if (nOldX <> m_nCurrX) or (nOldY <> m_nCurrY) then
begin
m_boDupMode := False;
Result := True;
end;
end;
end;

function TAIPlayObject.IsProperTarget(BaseObject: TBaseObject): Boolean;
begin
Result := False;
if inherited IsProperTarget(BaseObject) then begin
Result := True;
if BaseObject.m_btRaceServer = RC_ARCHERGUARD then begin //不主动攻击弓箭手
if BaseObject.m_TargetCret <> Self then Result := False;
end;
if BaseObject.m_Master <> nil then begin //不主动攻击宝宝
Result := False;
end;
if BaseObject.m_btRaceServer = RC_PLAYOBJECT then begin //不主动攻击弓人
if BaseObject.m_TargetCret <> Self then Result := False;
end;

if BaseObject.m_btRaceServer in [110, 111] then begin //不主动攻击沙巴克城门 沙巴克左城墙
Result := False;
end;
end;
end;

function TAIPlayObject.canatackTarget(BaseObject:TBaseObject): Boolean;

var
I : Integer;
noatackBaseObject : pTVisibleBaseObject;
begin
Result := true;
for I := 0 to m_noatcktActors.Count - 1 do
begin
noatackBaseObject := m_noatcktActors.Items[I];
if (TBaseObject(noatackBaseObject.BaseObject)=BaseObject) then
begin
Result := false;
break;
end;
end;
end;

procedure TAIPlayObject.SearchTargetxy();
var
BaseObject, BaseObject18 : TBaseObject;
i, nC, n10 ,nCheckCode ,n18 : integer;
VisibleBaseObject : pTVisibleBaseObject;
begin

try
n18 := 0;
while (True) do
begin
if m_VisibleActors.Count <= n18 then
break;
nCheckCode := 41;
VisibleBaseObject := m_VisibleActors.Items[n18];
nCheckCode := 42;
if VisibleBaseObject.nVisibleFlag = 0 then
begin
nCheckCode := 43;
m_VisibleActors.Delete(n18);
nCheckCode := 48;
Dispose(pTVisibleBaseObject(VisibleBaseObject)); //todo:dispose typeinfo
nCheckCode := 49;
Continue;
end;
nCheckCode := 50;
Inc(n18);
end;
except

end;

 

if (m_FirstTargetCret <> nil) then begin
if getAInoa(m_FirstTargetCret.m_sCharName) then DelTargetCreat();
end;

if (m_TargetCret <> nil) then begin
if getAInoa(m_TargetCret.m_sCharName) then DelTargetCreat();
end;

if ((m_TargetCret = nil) or (GetTickCount - m_dwSearchTargetTick > 1000)) and (m_boAIStart) then
begin
m_dwSearchTargetTick := GetTickCount();
// if (GetTickCount - m_dwStruckTick< 1000 ) then exit;
// m_dwStruckTick:= GetTickCount;

if (m_TargetCret = nil) then begin

BaseObject18 := nil;
n10 := 999;
if m_FirstTargetCret <> nil then begin
SetTargetCreat(m_FirstTargetCret);
Exit;
end;
for i := 0 to m_VisibleActors.Count - 1 do
begin
BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
if (not BaseObject.m_boDeath) then
begin

if canatackTarget(BaseObject) and IsProperTarget(BaseObject) and ((BaseObject.m_btRaceServer<> RC_PLAYOBJECT)) and (not BaseObject.m_boHideMode or m_boCoolEye)and (not getAInoa(BaseObject.m_sCharName)) then
begin

// MainOutMessage('检测目标通过:' + BaseObject.m_sCharName);

nC := abs(m_nCurrX - BaseObject.m_nCurrX) + abs(m_nCurrY - BaseObject.m_nCurrY);
if nC < n10 then
begin
n10 := nC;
BaseObject18 := BaseObject;
end;

if BaseObject.m_btRaceServer = 220 then
begin //仇恨图腾
BaseObject18 := BaseObject;
break;
end;

if (BaseObject.m_boTishen) and (BaseObject.m_nxiyingmon <= (BaseObject.m_btSlaveMakeLevel + 1)) then
begin
inc(BaseObject.m_nxiyingmon);
BaseObject18 := BaseObject;
break;
end;
end;
end;
end;
if BaseObject18 <> nil then begin

SetTargetCreat {FFF2}(BaseObject18);
lasttarget:=BaseObject18;
lasttargettick:=GetTickCount;
end;
// if (m_TargetCret <> nil) then MainOutMessage(Format('tatget:(%s)', [m_TargetCret.m_sCharName]));

end
else begin

if (m_TargetCret.m_btRaceServer = RC_PLAYOBJECT) or ((m_TargetCret.m_Master<>nil)) then begin
DelTargetCreat();
BaseObject18 := nil;
n10 := 999;
if m_FirstTargetCret <> nil then begin
SetTargetCreat(m_FirstTargetCret);
Exit;
end;
for i := 0 to m_VisibleActors.Count - 1 do
begin
BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
if (not BaseObject.m_boDeath) then
begin

if IsProperTarget(BaseObject) and ((BaseObject.m_btRaceServer<> RC_PLAYOBJECT)) and (not BaseObject.m_boHideMode or m_boCoolEye)and (not getAInoa(BaseObject.m_sCharName)) then
begin

 

nC := abs(m_nCurrX - BaseObject.m_nCurrX) + abs(m_nCurrY - BaseObject.m_nCurrY);
if nC < n10 then
begin
n10 := nC;
BaseObject18 := BaseObject;
end;

if BaseObject.m_btRaceServer = 220 then
begin //仇恨图腾
BaseObject18 := BaseObject;
break;
end;

if (BaseObject.m_boTishen) and (BaseObject.m_nxiyingmon <= (BaseObject.m_btSlaveMakeLevel + 1)) then
begin
inc(BaseObject.m_nxiyingmon);
BaseObject18 := BaseObject;
break;
end;
end;
end;
end;
if BaseObject18 <> nil then begin
SetTargetCreat {FFF2}(BaseObject18);
lasttarget:=BaseObject18;
lasttargettick:=GetTickCount;
end;

end;

end;

 

 

end;

end;

function TAIPlayObject.WarrAttackTarget(wMagIdx, wHitMode: Word): Boolean; {物理攻击}
var
I: Integer;
bt06,nDir: Byte;
boAttack,UseSkill: Boolean;
nRange: Integer;
UserMagic: pTUserMagic;
begin
Result := False;
if m_TargetCret <> nil then begin

nRange := 1;
if (wMagIdx = 58) or (wMagIdx = 77) then nRange := 4;
if (wMagIdx = 12) then nRange := 2;
//if (wMagIdx in [60]) then nRange := 6;
if (wMagIdx in [60, 61, 62]) then nRange := 12;

if CanAttack(m_TargetCret, nRange, bt06) then begin
m_dwTargetFocusTick := GetTickCount();

AttackDir(m_TargetCret, wHitMode, bt06);

BreakHolySeizeMode();
Result := True;
end else begin
if m_TargetCret.m_PEnvir = m_PEnvir then begin
SetTargetXY(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
end else begin
DelTargetCreat();
end;
end;
end;
end;

 

function TAIPlayObject.CanAttack(nCurrX, nCurrY: Integer; BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean;
var
I: Integer;
nX, nY: Integer;
begin
Result := False;
btDir := GetNextDirection(nCurrX, nCurrY, BaseObject.m_nCurrX, BaseObject.m_nCurrY);
for I := 1 to nRange do begin
if not m_PEnvir.GetNextPosition(nCurrX, nCurrY, btDir, I, nX, nY) then Break;
if (BaseObject.m_nCurrX = nX) and (BaseObject.m_nCurrY = nY) then begin
Result := True;
Break;
end;
end;
end;

function TAIPlayObject.CanAttack(BaseObject: TBaseObject; nRange: Integer; var btDir: Byte): Boolean;
var
I: Integer;
nX, nY: Integer;
begin
Result := False;
btDir := GetNextDirection(m_nCurrX, m_nCurrY, BaseObject.m_nCurrX, BaseObject.m_nCurrY);
for I := 1 to nRange do begin
if not m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, btDir, I, nX, nY) then Break;
if (BaseObject.m_nCurrX = nX) and (BaseObject.m_nCurrY = nY) then begin
Result := True;
Break;
end;
end;
end;

function TAIPlayObject.WarrorAttackTarget(wMagIdx: Integer): Boolean; {战士攻击}
var
//wHitMode: Word;
nSelectMagic: Integer;
UserMagic: pTUserMagic;
dwDelayTime: LongWord;
nDir: Byte;
boAttack: Boolean;
m_wHitMode: Integer;
begin
Result := False;
m_wHitMode := 0;

//MainOutMessage('WarrorAttackTarget1:' + IntToStr(m_nSelectMagic));
if wMagIdx > 0 then begin
UserMagic := GetUserMagic(wMagIdx);
if UserMagic <> nil then begin
case wMagIdx of
27, 39, 41: begin
Result := doSpell(UserMagic, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret); //战士魔法
//MainOutMessage('WarrorAttackTarget2:' + IntToStr(m_nSelectMagic));
//m_nSelectMagic := 0;
Exit;
end;

end;
case wMagIdx of
7: m_wHitMode := 3; //攻杀
12: m_wHitMode := 4; //使用刺杀
25: m_wHitMode := 5; //使用半月
26: m_wHitMode := 7; //使用烈火
40: m_wHitMode := 8; //抱月刀法
43: m_wHitMode := 11; //破空剑
58: m_wHitMode := 12; //开天斩
60: m_wHitMode := 13; //破魂斩
61: m_wHitMode := 14; //劈星斩
62: m_wHitMode := 15; //雷霆一
end;
end;
end;
Result := WarrAttackTarget(wMagIdx, m_wHitMode);
end;

function TAIPlayObject.WizardAttackTarget(wMagIdx: Integer): Boolean; {法师攻击}
var
wHitMode: Word;
nSelectMagic,m_wHitMode: Integer;
UserMagic: pTUserMagic;
dwDelayTime: LongWord;
begin
Result := False;
m_wHitMode := 0;
//MainOutMessage(m_sCharName + ' TAIObject.WizardAttackTarget 0');
if wMagIdx > 0 then begin
UserMagic := GetUserMagic(wMagIdx);
//MainOutMessage(m_sCharName + ' TAIObject.WizardAttackTarget 1');
if UserMagic <> nil then begin
//MainOutMessage(m_sCharName + ' TAIObject.WizardAttackTarget 2');
Result := doSpell(UserMagic, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret); //使用魔法
Exit;
end;
end;
Result := WarrAttackTarget(wMagIdx, m_wHitMode);
end;

function TAIPlayObject.TaoistAttackTarget(wMagIdx: Integer): Boolean; {道士攻击}
var
wHitMode: Word;
nSelectMagic,m_wHitMode: Integer;
UserMagic: pTUserMagic;
nIndex, nCount: Integer;
dwDelayTime: LongWord;
begin
Result := False;
m_wHitMode := 0;
if wMagIdx > 0 then begin
case wMagIdx of
SKILL_FIRECHARM {13},
SKILL_HANGMAJINBUB {14},
SKILL_DEJIWONHO {15},
SKILL_HOLYSHIELD {16},
SKILL_SKELLETON {17},
SKILL_CLOAK {18},
SKILL_BIGCLOAK {19},
SKILL_SINSU {30}

: begin
{if m_nSelectMagic = SKILL_FIRECHARM then begin
if not MagCanHitTarget(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY) then Exit;
end; }
// MainOutMessage('jineng:'+inttostr(wMagIdx)+':'+m_TargetCret.m_sCharName);
nCount := 1;
case wMagIdx of
SKILL_FIRECHARM {13}: nCount := 1;
SKILL_HANGMAJINBUB {14}: nCount := 1;
SKILL_DEJIWONHO {15}: nCount := 1;
SKILL_HOLYSHIELD {16}: nCount := 1;
SKILL_SKELLETON {17}: nCount := 1;
SKILL_CLOAK {18}: nCount := 1;
SKILL_BIGCLOAK {19}: nCount := 1;
SKILL_SINSU: {30} nCount := 5;
end;

 

end;

end;
UserMagic := GetUserMagic(wMagIdx);
if UserMagic <> nil then begin
if wMagIdx in [2, 14, 15] then Result := TPlayObject(self).doSpell(UserMagic, m_nCurrX, m_nCurrY, TPlayObject(self)) //使用魔法
else Result := TPlayObject(self).doSpell(UserMagic, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, m_TargetCret); //使用魔法

Exit;
end;
end;
Result := WarrAttackTarget(wMagIdx, m_wHitMode);
end;

{道士}

function TAIPlayObject.GetRandomConfigFileName: string;
var
I, nIndex: Integer;

sFileName: string;
LoadList: TStringList;
begin
Result := '';
if (m_sConfigListFileName <> '') and FileExists(g_Config.sEnvirDir + 'AI\AISET.TXT') then begin
LoadList := TStringList.Create;
try
LoadList.LoadFromFile(m_sConfigListFileName);
except

end;
nIndex := Random(LoadList.Count - 1);
if (nIndex >= 0) and (nIndex < LoadList.Count) then begin

Result := m_sFilePath + LoadList.Strings[nIndex];

 

end;
LoadList.Free;
end;
end;

function TAIPlayObject.FindMagic(sMagicName: string): pTUserMagic;
var
UserMagic: pTUserMagic;
I: Integer;
begin
Result := nil;
for I := 0 to m_MagicList.Count - 1 do begin
UserMagic := m_MagicList.Items[I];
if CompareText(UserMagic.MagicInfo.sMagicName, sMagicName) = 0 then begin
Result := UserMagic;
Break;
end;
end;
end;

 

procedure TAIPlayObject.Initialize;
var
I, nIndex: Integer;

sFileName: string;
ItemIni: TIniFile;

TempList: TStringList;
sCopyHumBagItems: string;
UserItem: pTUserItem;

sLineText: string;
sMagicName: string;
sItemName: string;
Magic: pTMagic;
MagicInfo: pTMagic;
UserMagic: pTUserMagic;
StdItem: pTStdItem;
LoadList: TStringList;
begin
// MainOutMessage(m_sCharName + ' :' + m_sConfigFileName);

if (m_sConfigFileName <> '') and FileExists(m_sConfigFileName) then begin
sFileName := m_sConfigFileName;
end else sFileName:=GetRandomConfigFileName ;

if (sFileName <> '') and FileExists(sFileName) then begin

ItemIni := TIniFile.Create(sFileName);
if ItemIni <> nil then begin
m_btJob := ItemIni.ReadInteger('BaseInfo', 'Job', random(2));
m_btGender := ItemIni.ReadInteger('BaseInfo', 'Gender', random(2));
m_btHair := ItemIni.ReadInteger('BaseInfo', 'Hair', random(2));
m_Abil.Level := ItemIni.ReadInteger('BaseInfo', 'Level', 1);

//MainOutMessage(m_sCharName + ' m_WAbil.Level:' + IntToStr(m_WAbil.Level));

sLineText := ItemIni.ReadString('BaseInfo', 'Magic', '');
if sLineText <> '' then begin
TempList := TStringList.Create;
// MainOutMessage(sLineText);
ExtractStrings(['|', '\', '/', ','], [], PChar(sLineText), TempList);
for I := 0 to TempList.Count - 1 do begin
sMagicName := Trim(TempList.Strings[I]);
if FindMagic(sMagicName) = nil then begin
// MainOutMessage(m_sCharName + ' 学:' + sMagicName);
Magic := UserEngine.FindMagic(sMagicName);
if Magic <> nil then begin
// MainOutMessage(m_sCharName + ' 学222:' + inttostr(Magic.btJob)+inttostr(m_btJob));
if (Magic.btJob = m_btJob) then begin
New(UserMagic);
UserMagic.MagicInfo := Magic;
UserMagic.wMagIdx := Magic.wMagicId;
UserMagic.btLevel := 3;
UserMagic.btKey := VK_F1;
UserMagic.nTranPoint := Magic.MaxTrain[3];
UserMagic.wPowerPermill := 0;

m_MagicList.Add(UserMagic);
// MainOutMessage(m_sCharName + '学习:' + sMagicName);
end;
end;
end;
end;
TempList.Free;
end;

sLineText := ItemIni.ReadString('BaseInfo', 'BagItem', '');
if sLineText <> '' then begin
TempList := TStringList.Create;
ExtractStrings(['|', '\', '/', ','], [], PChar(sLineText), TempList);
for I := 0 to TempList.Count - 1 do begin
sItemName := Trim(TempList.Strings[I]);

StdItem := UserEngine.GetStdItem(sItemName);
if StdItem <> nil then begin
New(UserItem);
if UserEngine.CopyToUserItemFromName(sItemName, UserItem) then begin
if not AddItemToBag(UserItem) then begin
Dispose(UserItem);
continue;
end;
// MainOutMessage(m_sCharName + '获得:' + sItemName);

end else Dispose(UserItem);
end;

end;
TempList.Free;
end;

UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'DRESSNAME', ''), @m_UseItems[U_DRESS]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'WEAPONNAME', ''), @m_UseItems[U_WEAPON]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'RIGHTHANDNAME', ''), @m_UseItems[U_RIGHTHAND]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'NECKLACENAME', ''), @m_UseItems[U_NECKLACE]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'HELMETNAME', ''), @m_UseItems[U_HELMET]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'ARMRINGLNAME', ''), @m_UseItems[U_ARMRINGL]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'ARMRINGRNAME', ''), @m_UseItems[U_ARMRINGR]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'RINGLNAME', ''), @m_UseItems[U_RINGL]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'RINGRNAME', ''), @m_UseItems[U_RINGR]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'BUJUKNAME', ''), @m_UseItems[U_BUJUK]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'BELTNAME', ''), @m_UseItems[U_BELT]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'BOOTSNAME', ''), @m_UseItems[U_BOOTS]);
UserEngine.MakeNewItem(ItemIni.ReadString('UseItems', 'CHARMNAME', ''), @m_UseItems[U_CHARM]);

m_boNoDropItem := ItemIni.ReadBool('UseItems', 'NoDropItem', False);
m_boNoDropUseItem := ItemIni.ReadBool('UseItems', 'NoDropUseItem', False);

ItemIni.Free;
HasLevelUp(m_Abil.Level - 1);

m_Abil.HP:=m_Abil.HP+2000;
m_Abil.MP:=m_Abil.MP+2000;

end;
end;
inherited;
end;

 

 

procedure TAIPlayObject.Run;
var
nX, nY, i, count, nDir , nEscapeDis : Integer;
VisibleMapItem : pTVisibleMapItem;
doskill : boolean;
UserMagic : pTuserMagic;
nSelectMagic,nCheckCode: Integer;
ncaord:string;
bt06 : Byte;
nValue,nPercent:integer;
UseQueueSkill, addhpmode, toofar, toonear, UseSkill: boolean;
begin

// try
doskill:=False;
if (GetTickCount - m_dwclearnoatackTick) > 3*60*1000 then begin
try
m_dwclearnoatackTick:= GetTickCount;
for I := 0 to m_noatcktActors.Count - 1 do
begin
pTVisibleBaseObject(m_noatcktActors.Items[I]).nVisibleFlag := 0;
end;
except
MainOutMessage(format('sExceptionMsg1:%d', [nCheckCode]));
KickException();
end;

end;

if (m_TargetCret<>nil) then begin
if m_TargetCret.m_boDeath or m_TargetCret.m_boGhost then DelTargetCreat();
end;

if not m_boDeath and not m_boGhost then m_dwDeathTick:= GetTickCount();
if (GetTickCount() - m_dwDeathTick > 3000) then begin
MakeGhost();
m_boDeleted:=true;
// UserEngine.AddToAIHumanFreeList(self);
end;

if m_ManagedEnvir <> m_PEnvir then begin
m_ManagedEnvir := m_PEnvir;
DelTargetCreat();
end;
if (not m_boAIStart) then
DelTargetCreat();
ncaord:='201';

{ if m_nMoveFailCount> 8 then begin
m_nMoveFailCount:=0;
DelTargetCreat();
end; }

if (m_TargetCret <> nil) then begin

if ( GetTickCount-lasttargettick>7000 ) and (m_TargetCret.m_sCharName = lasttarget.m_sCharName) and (m_TargetCret.m_WAbil.MaxHP *97/100< m_TargetCret.m_WAbil.HP) then begin

//MainOutMessage(m_sCharName + '不攻击怪物:'+lasttarget.m_sCharName);
UpdatenoatcktActors(lasttarget);
DelTargetCreat();;

end;

end;

if {((GetTickCount - m_dwSearchEnemyTick) > 10000) or }(((GetTickCount - m_dwSearchEnemyTick) > 1000) and (m_TargetCret = nil)) then
begin
m_dwSearchEnemyTick := GetTickCount();
SearchTargetxy();
end;

 

toonear := false;
toofar := false;

if not m_boDeath and not m_boGhost and not m_boStoneMode and (m_wStatusTimeArr[POISON_STONE {5 0x6A}] = 0) then
begin
addhpmode := (m_WAbil.HP * 2 <= m_WAbil.MaxHP) ; //逃跑

if GetTickCount - m_dwAutoAddHealthTick > 1000 then begin

// MainOutMessage(m_sCharName + 'jiaxue:');
m_dwAutoAddHealthTick := GetTickCount;
nPercent := m_WAbil.HP * 100 div m_WAbil.MaxHP;
nValue := m_WAbil.MaxHP div 10;
if nPercent < 70 then begin
if m_WAbil.HP + nValue >= m_WAbil.MaxHP then begin
m_WAbil.HP := m_WAbil.MaxHP;
end else begin
Inc(m_WAbil.HP, nValue);

end;
end;
nPercent := m_WAbil.MP * 100 div m_WAbil.MaxMP;

if nPercent < 70 then m_WAbil.MP := m_WAbil.MaxMP;
end;

 

UseSkill := HaveSingleMagic(m_btJob);

if m_boWalkWaitLocked then
begin
if (GetTickCount - m_dwWalkWaitTick) > m_dwWalkWait then
begin
m_boWalkWaitLocked := False;
end;
end;

if not m_boWalkWaitLocked and (Integer(GetTickCount - m_dwWalkTick) > g_Config.dwRunAI) then
begin
m_dwWalkTick := GetTickCount();
Inc(m_nWalkCount);
if m_nWalkCount > m_nWalkStep then
begin
m_boWalkWaitLocked := True;
m_dwWalkWaitTick := GetTickCount();
end;

if (m_TargetCret <> nil) then begin
nSelectMagic := SelectMagic;
if (m_btJob>0) and (m_btJob>0) and (abs(m_nCurrX - m_TargetCret.m_nCurrX) <= 2) and (abs(m_nCurry - m_TargetCret.m_nCurry) <= 2) then
toonear := true ;

if (abs(m_nCurrX - m_TargetCret.m_nCurrX) >= 6) or (abs(m_nCurry - m_TargetCret.m_nCurry) >= 6) then
toofar := true;

// 远近调节

if toofar or ( ((m_btJob=0) or (not UseSkill)) and ((abs(m_nCurrX - m_TargetCret.m_nCurrX) > 1) or (abs(m_nCurry - m_TargetCret.m_nCurry) > 1))) then begin

// MainOutMessage(m_sCharName + 'kaojin:'+inttostr(abs(m_nCurrX - m_TargetCret.m_nCurrX)));
nDir := GetNextDirection(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, nDir, 2, m_nTargetX, m_nTargetY); //004A93B5 0FFE
//if GetTickCount - m_dwWalkTick > g_Config.dwRunAI then begin
// m_dwWalkTick:= GetTickCount;
if not runto(nDir, false, m_nTargetX, m_nTargetY) then GotoTargetXY();
inc(m_nMoveFailCount);
exit;
// end;

end;

if UseSkill and toonear then
begin
// MainOutMessage(m_sCharName + 'yuanli:'+inttostr(abs(m_nCurrX - m_TargetCret.m_nCurrX)));
nDir := GetNextDirection(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
nDir := GetBackDir(nDir);
m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, nDir, 5, m_nTargetX, m_nTargetY);

if not runto(nDir, false, m_nTargetX, m_nTargetY) then
GotoTargetXY;
Exit;
// end;
end;

 

if toofar then
begin
nEscapeDis := 3;
nDir := GetNextDirection(m_nCurrX, m_nCurrY, m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY);
m_PEnvir.GetNextPosition(m_TargetCret.m_nCurrX, m_TargetCret.m_nCurrY, nDir, nEscapeDis, m_nTargetX, m_nTargetY);
//if GetTickCount - m_dwWalkTick > g_Config.dwRunAI then begin
// m_dwWalkTick:= GetTickCount;
if not runto(nDir, false, m_nTargetX, m_nTargetY) then GotoTargetXY;

Exit;
// end;
end;
// 远近调节

if (Integer(GetTickCount - m_dwPiosonTick) > m_nNextPOISONTime) then
begin
m_dwPiosonTick := gettickCount;
UserMagic := GetMagicInfo(SKILL_AMYOUNSUL); //施毒术
if (UserMagic <> nil) then
begin
m_dwHitTick := GetTickCount();
SkillAttack(UserMagic, m_TargetCret);
Exit;
end;
end;

UserMagic := GetMagicInfo(31); //如果有魔法盾且魔法盾没有开
if (not doskill) and (UserMagic <> nil) and (not m_boAbilMagBubbleDefence) then
begin // m_wStatusTimeArr[STATE_BUBBLEDEFENCEUP]=0
// if MagicManager.DoSpell(Self,UserMagic,m_nCurrX,m_nCurrY,self) then
if DoSpell(UserMagic, m_nCurrX, m_nCurrY, self) then
doskill := true;
end;

UserMagic := GetMagicInfo(61); // //如果有金刚且金刚没有开
if (not doskill) and (UserMagic <> nil) and (not m_boAbilMagPowerDefence) then
begin //(m_wStatusArrValue[6]=0)
// if MagicManager.DoSpell(Self,UserMagic,m_nCurrX,m_nCurrY,self) then
if DoSpell(UserMagic, m_nCurrX, m_nCurrY, self) then
doskill := true;
end;

UserMagic := GetMagicInfo(42); // //如果有护身真气且护身真气没有开
if (not m_boAbilMagPowerDefence) and (not doskill) and (UserMagic <> nil) and (not m_boAbilMagzqDefence) then
begin // (m_wStatusTimeArr[STATE_14]=0)
// if MagicManager.DoSpell(Self,UserMagic,m_nCurrX,m_nCurrY,self) then
if DoSpell(UserMagic, m_nCurrX, m_nCurrY, self) then
doskill := true;
end;

UserMagic := GetMagicInfo(70); // //如果有风影且风影没有开
if (not doskill) and (UserMagic <> nil) and (not m_boAbilMagfyDefence) then
begin // m_wStatusArrValue[7]=0
// if MagicManager.DoSpell(Self,UserMagic,m_nCurrX,m_nCurrY,self) then
if DoSpell(UserMagic, m_nCurrX, m_nCurrY, self) then
doskill := true;
end;

 

if doskill then begin
m_dwHitTick := GetTickCount();
Exit;
end;

// m_dwSkillTick := GetTickCount;
case m_btJob of
0: begin
if (m_TargetCret <> nil) and (Integer(GetTickCount - m_dwHitTick) > g_Config.se26) then begin
m_dwHitTick := GetTickCount();
// MainOutMessage(m_sCharName + 'jineng0:'+inttostr(nSelectMagic));
if ActThink(nSelectMagic) then begin
//inherited;
//Exit;
end;

if (m_TargetCret <> nil) and StartAttack(nSelectMagic) then begin
if (nSelectMagic > 0) and (nSelectMagic <= High(m_SkillUseTick)) then begin
m_SkillUseTick[nSelectMagic] := GetTickCount;
end;
end;
end;
end;
1: begin
if (m_TargetCret <> nil) and (Integer(GetTickCount - m_dwHitTick) > g_Config.se27) then begin
m_dwHitTick := GetTickCount();
// MainOutMessage(m_sCharName + 'jineng1:'+inttostr(nSelectMagic));
if ActThink(nSelectMagic) then begin
//inherited;
//Exit;
end;

if (m_TargetCret <> nil) and StartAttack(nSelectMagic) then begin
if (nSelectMagic >= 0) and (nSelectMagic <= High(m_SkillUseTick)) then begin
m_SkillUseTick[nSelectMagic] := GetTickCount;
end;
end;
end;
end;
2: begin
if (m_TargetCret <> nil) and (Integer(GetTickCount - m_dwHitTick) > g_Config.se28) then begin
m_dwHitTick := GetTickCount();
// MainOutMessage(m_sCharName + 'jineng2:'+inttostr(nSelectMagic));
if ActThink(nSelectMagic) then begin
//inherited;
//Exit;
end;

if (m_TargetCret <> nil) and StartAttack(nSelectMagic) then begin
if (nSelectMagic >= 0) and (nSelectMagic <= High(m_SkillUseTick)) then begin
m_SkillUseTick[nSelectMagic] := GetTickCount;
end;
end;
end;
end;
end;
// end;

BreakHolySeizeMode();
end else begin

ncaord:='203';
if StartPickUpItem(500) then begin //捡物

Exit;
end;

Wonderingai();
exit;

ncaord:='205';
end;

end;

end;
inherited;
end;

function TAIPlayObject.SkillAttack(UserMagic: pTuserMagic; TargetCret: TBaseObject): boolean;
begin
result := MagicManager.DoSpell(Self, UserMagic, TargetCret.m_nCurrX, TargetCret.m_nCurrY, TargetCret);
end;

function TAIPlayObject.SkillAttackOfSoldier(UserMagic: pTuserMagic; nDir: word; TargetCret: TBaseObject): boolean;
var
nPower, MagicId : Integer;
wIdent : word;

//半月攻击

function SwordWideAttack(UserMagic: pTuserMagic): Boolean; //004C1CDC
var
nC, n10 : Integer;
nX, nY : Integer;
BaseObject : TBaseObject;
begin
Result := False;
nC := 0;
while (True) do
begin
n10 := (m_btDirection + g_Config.WideAttack[nC]) mod 8;
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, n10, 1, nX, nY) then
begin
BaseObject := m_PEnvir.GetMovingObject(nX, nY, True);
if (BaseObject <> nil) and IsProperTarget(BaseObject) then
begin
Result := SkillDamage(UserMagic, BaseObject);
SetTargetCreat(BaseObject);
end;
end;
Inc(nC);
if nC >= 3 then
break;
end;
end;

function CrsWideAttack(UserMagic: pTuserMagic): Boolean;
var
nC, n10 : Integer;
nX, nY : Integer;
BaseObject : TBaseObject;
begin
Result := False;
nC := 0;
while (True) do
begin
n10 := (m_btDirection + g_Config.CrsAttack[nC]) mod 8;
if m_PEnvir.GetNextPosition(m_nCurrX, m_nCurrY, n10, 1, nX, nY) then
begin
BaseObject := m_PEnvir.GetMovingObject(nX, nY, True);
if (BaseObject <> nil) and IsProperTarget(BaseObject) then
begin
Result := SkillDamage(UserMagic, BaseObject);
SetTargetCreat(BaseObject);
end;
end;
Inc(nC);
if nC >= 7 then
break;
end;
end;

begin
result := false;
MagicId := UserMagic.MagicInfo.wMagicID;
case MagicId of
SKILL_FIRESWORD:
wIdent := RM_FIREHIT;
SKILL_ERGUM:
wIdent := RM_CRSHIT;
SKILL_BANWOL:
begin
wIdent := RM_WIDEHIT;
SwordWideAttack(UserMagic);
SendAttackMsg(wIdent, nDir, TargetCret.m_nCurrX, TargetCret.m_nCurrY, MagicId);
result := true;
Exit;
end;
SKILL_44, 59, 60:
wIdent := RM_25; //雷霆剑、破击剑法、破盾斩,抱月
SKILL_43:
begin
wIdent := RM_25;
CrsWideAttack(UserMagic);
SendAttackMsg(wIdent, nDir, TargetCret.m_nCurrX, TargetCret.m_nCurrY, MagicId);
result := true;
Exit;
end;
SKILL_YEDO:
wIdent := RM_SPELL2; //攻杀剑法
SKILL_MOOTEBO:
begin
result := DoMotaebo(nDir, 3, 0);
Exit;
end;
62:
begin //突斩
result := DoMotaebo(nDir, 3, 2);
Exit;
end;
end;
SkillDamage(UserMagic, TargetCret);
SendAttackMsg(wIdent, nDir, TargetCret.m_nCurrX, TargetCret.m_nCurrY, MagicId);
result := true;
end;

function TAIPlayObject.HaveQueueMagic(AJob: byte): Boolean;
var
i : integer;
nMagicId : set of byte;
begin
result := false;
case AJob of
0:
nMagicId := QueueMagicOfJob0;
1:
nMagicId := QueueMagicOfJob1;
else
Exit;
end;
for i := 0 to m_MagicList.Count - 1 do
if ptusermagic(m_MagicList[i]).wMagIdx in nMagicId then
begin
result := true;
break;
end;
end;

function TAIPlayObject.getEscapeMagic(AJob: byte): pTMagic;
var
nMagicId : word;
i : integer;
begin
result := nil;
case AJob of
0:
nMagicId := 77;
1:
nMagicId := 35;
2:
nMagicId := 75;
else
Exit;
end;
for i := 0 to m_MagicList.Count - 1 do
if ptusermagic(m_MagicList[i]).wMagIdx = nMagicId then
begin
result := ptusermagic(m_MagicList[i]).MagicInfo;
break;
end;
end;

function TAIPlayObject.GetAttackCount: integer;
var
BaseObject : TBaseObject;
i : Integer;
begin
result := 0;
for i := 0 to m_VisibleActors.Count - 1 do
begin
BaseObject := TBaseObject(pTVisibleBaseObject(m_VisibleActors.Items[i]).BaseObject);
if not BaseObject.m_boDeath then
if (not BaseObject.m_boHideMode or m_boCoolEye) then
if BaseObject.m_TargetCret = self then
inc(Result);
end;
end;
function TAIPlayObject.SkillDamage(UserMagic: pTuserMagic; TargetCret: TBaseObject): boolean;
var
nPower : integer;
begin
nPower := GetAttackPower(LoWord(m_WAbil.DC), SmallInt(HiWord(m_WAbil.DC) - LoWord(m_WAbil.DC)));
if nPower > 0 then
nPower := TargetCret.GetHitStruckDamage(Self, nPower);
if nPower > 0 then
begin
nPower := nPower + (UserMagic.MagicInfo.wPower + Random(UserMagic.MagicInfo.wMaxPower - UserMagic.MagicInfo.wPower));
TargetCret.StruckDamage(nPower);
TargetCret.SendDelayMsg(TBaseObject(RM_STRUCK), RM_10101, nPower, TargetCret.m_WAbil.HP, TargetCret.m_WAbil.MaxHP, Integer(Self), '', 200);
end;
// SendDelayMsg (self, RM_DELAYMAGIC, nPower, MakeLong(TargetCret.m_nCurrX,TargetCret.m_nCurrY),2,integer(TargetCret), '', 600);
end;

function TAIPlayObject.HaveSingleMagic(AJob: byte): Boolean;
var
i : integer;
nMagicId : set of byte;

begin
result := false;
case AJob of
0:
nMagicId := SingleMagicOfJob0;
1:
nMagicId := SingleMagicOfJob1;
2:
nMagicId := SingleMagicOfJob2;
else
Exit;
end;
for i := 0 to m_MagicList.Count - 1 do begin
// MainOutMessage(m_sCharName + 'jineng'+inttostr(AJob)+':+'+inttostr(ptusermagic(m_MagicList[i]).wMagIdx));
if ptusermagic(m_MagicList[i]).wMagIdx in nMagicId then
begin
result := true;
break;
end;

end;

end;

function TAIPlayObject.StartPickUpItem(nPickUpTime: Integer): Boolean;
function PickUpItem(nX, nY: Integer; SelItemObject: pTMapItem): Boolean;
var
UserItem: pTUserItem;
StdItem: pTStdItem;
ItemObject: TObject;
nDeleteCode: Integer;
PlayObject: TPlayObject;
MapItem : pTMapItem;
begin
Result := False;
MapItem := m_PEnvir.GetItem(nX, nY);
if ItemObject = nil then Exit;
//捡钱
if m_PEnvir.DeleteFromMap(nX, nY,OS_ITEMOBJECT, TObject(MapItem)) = 1 then begin
Dispose(pTMapItem(MapItem));
SendRefMsg(RM_ITEMHIDE, 0, Integer(ItemObject), nX, nY, '');
Result := True;

end;
Exit;

end;

 

function CanPickUp(ItemObject: pTMapItem): Boolean;
var
I: Integer;
nItemBind: Integer;
begin
Result := True;
{ for I := 0 to m_NotCanPickItemList.Count - 1 do begin
if m_NotCanPickItemList.Items[I] = ItemObject then begin
Result := False;
Exit;
end;
end;
if g_Config.boBindItemNoPickUp then begin
nItemBind := CheckItemBindUse(@ItemObject.m_UserItem, False);
if (nItemBind > 0) and (nItemBind <> 2) then begin
Result := False;
end;
end; }

end;

function FindPickItem(): pTMapItem;
var
ItemList: TList;
ItemObject: pTMapItem;
ItemObjectA: pTMapItem;
BaseObject: TBaseObject;
I, nX, nY: Integer;
nStartX: Integer;
nEndX: Integer;
nStartY: Integer;
nEndY: Integer;
n01, n02: Integer;
nError: Integer;
MapCellInfo: pTMapCellinfo;
VisibleMapItem: pTVisibleMapItem;
begin
Result := nil;
ItemObjectA := nil;
n01 := 9999;

nError := -4;
for I := 0 to m_VisibleItems.Count - 1 do begin
VisibleMapItem := m_VisibleItems.Items[I];
nError := 1;
ItemObject := VisibleMapItem.MapItem;
nError := 2;
if ItemObject <> nil then begin
nError := 3;
if (CanPickUp(ItemObject)) then begin
nError := 4;
//sItemName := ItemObject.m_sName;
//nError := 44;
if ItemObject.OfBaseObject = nil then Continue;

// MainOutMessage(m_sCharName + '捡东西');

if (ItemObject.OfBaseObject = Self) then begin
nError := 6;
if (abs(VisibleMapItem.nX - m_nCurrX) <= 6) and (abs(VisibleMapItem.nY - m_nCurrY) <= 6) then begin
nError := 7;
if (ItemObject <> m_SelItemObject) then begin
nError := 8;
n02 := abs(VisibleMapItem.nX - m_nCurrX) + abs(VisibleMapItem.nY - m_nCurrY);
nError := 9;
if n02 < n01 then begin
n01 := n02;
ItemObjectA := ItemObject;
end;
nError := 10;
end;
end;
end;

end;
end;
end;

if ItemObjectA <> nil then Result := ItemObject;
end;

var
ItemObject: pTMapItem;
resourcestring
sExceptionMsg = '[Exception] TCopyObject::PickUpItem 1-%d %s %s %d %d %d';
begin
Result := False;

if (not IsEnoughBag) or m_boDeath or m_boGhost {or (not m_boCanPickUpItem)} then Exit;
{
if m_SelItemObject <> nil then begin

m_nTargetX:= VisibleMapItem.nX;
m_nTargetY:= VisibleMapItem.nY;

if g_ItemManager.FindItem(m_PEnvir, m_nCurrX, m_nCurrY, m_SelItemObject) = m_SelItemObject then begin
if PickUpItem(m_nCurrX, m_nCurrY, m_SelItemObject) then begin
m_SelItemObject := nil;
Result := True;
Exit;
end else begin
m_NotCanPickItemList.Add(m_SelItemObject);
m_SelItemObject := nil;
end;
end else m_SelItemObject := nil;
end;
}
ItemObject := FindPickItem();
if ItemObject <> nil then begin
m_SelItemObject := ItemObject;
if (m_nCurrX <> TBaseObject(ItemObject).m_nMapX) or (m_nCurrY <> TBaseObject(ItemObject).m_nMapY) then begin
if not GotoNextOne(TBaseObject(ItemObject).m_nMapX, TBaseObject(ItemObject).m_nMapY, True) then begin
// m_NotCanPickItemList.Add(m_SelItemObject);
m_SelItemObject := nil;
end;
end;
Result := True;
end;
end;

procedure TAIPlayObject.UpdatenoatcktActors(BaseObject: TBaseObject); //004B939C
var
I : Integer;
boIsVisible : Boolean;
VisibleBaseObject : pTVisibleBaseObject;
begin
boIsVisible := False;
// if (BaseObject.m_btRaceServer = RC_PLAYOBJECT) or (BaseObject.m_Master <> nil) then
// m_boIsVisibleActive:=True;//如果是人物或宝宝则置TRUE
for I := 0 to m_noatcktActors.Count - 1 do
begin
VisibleBaseObject := m_noatcktActors.Items[I];
if VisibleBaseObject.BaseObject = BaseObject then
begin
VisibleBaseObject.nVisibleFlag := 1;
boIsVisible := True;
break;
end;
end;
if boIsVisible then
exit;
New(VisibleBaseObject);
VisibleBaseObject.nVisibleFlag := 2;
VisibleBaseObject.BaseObject := BaseObject;
m_noatcktActors.Add(VisibleBaseObject);
end;

constructor TAIPlayObject.Create;
begin
inherited;
m_boDupMode := False;
m_boFixedHideMode := false;
bo554 := False;
m_dwThinkTick := GetTickCount();
m_dwuseskilltick := GetTickCount();
m_nViewRange := 5;
m_nRunTime := 100+ Random(50);
m_dwSearchTime := 3000*(100-g_Config.dwAIADDTime) div 100 + Random(2000);
m_dwSearchTick := GetTickCount();
m_nWalkSpeed := 700;
m_nNextHitTime := 1200;
m_nNextSkillTime := 1200;
m_nNextEscapeTime := 60 * 1000 * 2;
m_nNextPOISONTime := 15 * 1000;
m_nNextQueueTime := 10 * 1000;
m_nNextPushTime := 10 * 1000;
m_btRaceServer := 1;
//UserEngine.makenewplay(,self);
nskill := 0;
m_dwclearnoatackTick:= GetTickCount();
m_dwSearchTargetTick:= GetTickCount();
m_nIncSelfHealthCount:=0;
//StartAI(t_Dynamic);
m_dwSearchEnemyTick := GetTickCount();
m_nround:=1000;
m_boAI := True;
m_boLoginNoticeOK := True;
m_boAIStart := false; //开始挂机
m_ManagedEnvir := nil; //挂机地图
m_Path := nil;
m_nPostion := -1;
m_sFilePath := '';
m_sConfigFileName := '';
m_sHeroConfigFileName := '';
m_sConfigListFileName := '';
m_PointManager := TPointManager.Create(Self);
nDieDropUseItemRate:= 10;
// m_dwAITick := GetTickCount();
m_dwEscapeTime := 0;
m_SelItemObject := nil;
m_dwAutoAddHealthTick:= GetTickCount();
lasttarget:=nil;
m_noatcktActors := TList.Create;
m_Trjj := 0;
m_Trfl := 0;
m_Tryl := 0;
m_TrMaxyl := 0;
m_nTyxf := 0;
m_nTyMin := 0;
m_nTyMax := 0;
m_ndrakHit := 0;
end;

destructor TAIPlayObject.Destroy;
var
i:Integer;
begin
m_Path := nil;
m_PointManager.Free;
for I := m_noatcktActors.Count - 1 downto 0 do
begin
Dispose(pTVisibleBaseObject(m_noatcktActors.Items[I]));
end; //004B8296
m_noatcktActors.Free;
inherited;
end;

procedure TAIPlayObject.Die;
begin
if m_boAIStart then begin
m_boAIStart := False;
m_ManagedEnvir := nil;
end;
inherited;
end;

procedure TAIPlayObject.MakeGhost(); //004BB300
begin

if m_boAIStart then begin
m_boAIStart := False;
m_ManagedEnvir := nil;
end;
inherited;
end;

 

procedure TAIPlayObject.StartAI(PathType: TPathType);
begin
if (not m_boGhost) and
(not m_boDeath) and
(not m_boAIStart) then begin
m_ManagedEnvir := m_PEnvir;
m_PointManager.PathType := PathType;
m_PointManager.Initialize(m_PEnvir);
m_boAIStart := True;

m_nMoveFailCount := 0;
// MainOutMessage(m_sCharName + ' TAIObject.Start:' + IntToStr(m_PointManager.Count));
if g_FunctionNPC <> nil then begin
m_nScriptGotoCount := 0;
g_FunctionNPC.GotoLable(TPlayObject(Self), '@AIStart', False);
end;
end;
end;

procedure TAIPlayObject.Stop;
begin
if m_boAIStart then begin
m_boAIStart := False;
m_ManagedEnvir := nil;
m_nMoveFailCount := 0;
m_Path := nil;
m_nPostion := -1;
//MainOutMessage(m_sCharName + ' TAIObject.Stop:' + IntToStr(m_PointManager.Count));
if g_FunctionNPC <> nil then begin
m_nScriptGotoCount := 0;
g_FunctionNPC.GotoLable(Self, '@AIStop', False);
end;
end;
end;

end.

评论

发表评论必须先登陆, 您可以 登陆 或者 注册新账号 !


在线咨询: 问题反馈
客服QQ:174666394

有问题请留言,看到后及时答复