procedure TForm1.Button1Click(Sender: TObject);
var
ss:TStringList ;
s:string;
begin
ss:=TStringList.Create;
if Length( Memo4.Text)< 20 then Memo5.Lines.Add('内容太短');
if Edit18.Text ='' then Edit18.Text:=Copy(Memo4.Text,1,30) ;
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;
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
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;
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;
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;
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);
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;
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;
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;
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
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;
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;
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);
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);
// 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
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
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;
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;
Xml \ OtherTipsCfg.xml ;//单文件不建议超过6000行,否则Win10以下的系统容易出现游戏异常,地图错乱等问题
Xml \ OtherTipsCfg2.xml ;//单文件不建议超过6000行,否则Win10以下的系统容易出现游戏异常,地图错乱等问题
Xml \ OtherTipsCfg3.xml ;//单文件不建议超过6000行,否则Win10以下的系统容易出现游戏异常,地图错乱等问题
Xml \ OtherTipsCfg4.xml ;//单文件不建议超过6000行,否则Win10以下的系统容易出现游戏异常,地图错乱等问题
A = 地图编号
B = X坐标
C = Y坐标
备注1:当前指定点击后,会检测是否拥有 !Setup.txt FlyName= 内的物品道具
备注2:如果拥有!Setup.txt FlyName= 内的物品道具,将自动扣走并传送,如没有则会提示!
备注3:当前指令内的A B C参数,只支持数字
脚本举例: ;// !Setup.txt [Server]
FlyName=飞行靴
当玩家角色点击<@@flytoplace A B C> ,系统会自动检测玩家是否拥有飞行靴,如果有则自动扣走并传送!
11、扩展:@@special A B C ;//点击后将触发 QFunction-0.txt [@任务标签触发]
10、扩展:MISSION A B C ;// 扩展地图标签类命令支持SELF,如果填写SELF,则效验人物所在地图(可适用于副本参数地图)
PARAM1 D
PARAM2 E
PARAM3 F
PARAM4 G
MOBPLACE H
A = 地图编号 ;// 怪物集结点地图编号 如果填写SELF,则刷新到人物所在地图(可适用于副本参数地图)
B = 坐标X ;// 怪物集结点地图坐标X
C = 坐标Y ;// 怪物集结点地图坐标Y
D = 坐标X ;// 怪物刷新坐标X
E = 坐标Y ;// 怪物刷新坐标Y
F = 数量
G = 范围
H = 怪物名字
11、新增:MissionNearMon A B C 刷新出来的怪物会朝 人物执行当前命令时 的坐标集合
A = 名字
B = 范围
C = 数量
12、新增:CheckNearbyMonCount A B C 检测人物当前范围内有多少怪物
A = 范围
B = > < =
C = 数量
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GameShow更新日志 For 20190402
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1.扩展功能:单体组合
2.扩展功能:器魂属性
客户端文件:xml \ SoulLevelUpExpCfg.xml
详细介绍请查看更新包:[ 0. 客户端 GsRes ]-[ xml \ SoulLevelUpExpCfg.xml ]的介绍
GameShow更新日志 For 20190215
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ① 客户端新增文件:xml \ dneffect.xml
针对物品名字给予物品赋值地面的特效 语句案例:
② 新增指令:KillToGetitem A
//执行的玩家死亡时必爆出A装备 A=装备位置 ( A = 99 代表关闭当前功能) ③ 修复指令:KILLMONBURSTRATE
调整玩家杀怪的爆率
A 爆率翻倍 数值÷100才是实际调整的倍数,100、200、300以此类推
B 有效时间 单位:秒
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GameShow更新日志 For 20190108
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ① 新增脚本:ADDBUFF 参数1 参数1:xml / GsDiymagic.xml 里的 魔法树 标签
( 支持读取:20000-29999的标签 ) 关于GsDiymagic.xml的编辑,建议先下载NotePad++
百度官方下载地址:http://rj.baidu.com/soft/detail/13478.html?ald
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GameShow更新日志 For 20190101
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AccountWnd.xml
<UiEffect unit_idx ="0" name = "" Packid = "0" Index = "0" X = "100" Y = "200" bShow = "0"/>
<UiEffect unit_idx ="1" name = " " Packid = "3" Index = "56001" X = "132" Y = "230" bShow = "1"/>
<UiEffect unit_idx ="2" name = " " Packid = "3" Index = "1658" X = "100" Y = "200" bShow = "0"/>
<UiEffect unit_idx ="3" name = "button3" Packid = "3" Index = "1662" X = "0" Y = "200" bShow = "0"/>
<UiEffect unit_idx ="4" name = "button4" Packid = "3" Index = "1662" X = "100" Y = "200" bShow = "0"/>
<UiEffect unit_idx ="5" name = "button5" Packid = "3" Index = "1662" X = "181" Y = "300" bShow = "1"/>
<UiEffect unit_idx ="6" name = "关闭" Packid = "3" Index = "56009" X = "375" Y = "95" bShow = "1"/>
<UiEffect unit_idx ="7" name = "Edit1" Packid = "142" Index = "18" X = "135" Y = "119" bShow = "1"/>
<UiEffect unit_idx ="8" name = "Edit2" Packid = "142" Index = "18" X = "135" Y = "150" bShow = "1"/>
GameShow更新日志 For 20180111
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ① 【怪物相关】修复MapQuest.txt文件 第一个参数(地图编号) 为 *号时候所有地图触发无效的问题 ② 【坐骑相关】新增下马命令 DISHORSE , 执行当前命令后,玩家将自动下马
GameShow更新日志 For 20180103
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ① 【寄售系统】重新编写寄售系统数据库结构,减少寄售数据的占用封包 ② 【寄售系统】新增脚本命令:JSGETBACK 参数一
(功能:取回或购买寄售物品后,需要执行当前脚本商品在背包自动刷新) 参数一 = 当前涉及商品的IDX
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GameShow更新日志 For 20180101
*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ① 【寄售系统】新增变量:$JSSJ.A.B
参数A = 1~2
1 = 寄售的商品数量
2 = 寄售出售后存在数据里的货币值
A = 1 的时候 B = 寄售物品类型
A = 2 的时候 B = 货币类型