⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monsterai.pas

📁 RO模拟器!!适合玩仙境传说的玩家们呦~
💻 PAS
📖 第 1 页 / 共 5 页
字号:
unit MonsterAI;

interface

uses
	Windows, StdCtrls, MMSystem, Classes, SysUtils, ScktComp, List32, Common, Path;

        procedure CalcAI(tm:TMap; ts:TMob; Tick:Cardinal);
        procedure MobSpawn(tm:TMap; ts:TMob; Tick:cardinal);
        //procedure MobSkillCalc(tm:TMap;ts:TMob;Tick:cardinal);
        //procedure MobSkillChance(tm:TMap; ts:TMob; tsAI:TMobAIDB; Tick:cardinal);
        procedure MobSkills(tm:TMap; ts:TMob; Tick:cardinal);
        procedure MobFieldSkills(tm:TMap; ts:TMob; Tick:cardinal);
        procedure MobStatSkills(tm:TMap; ts:TMob; Tick:cardinal);
        procedure MobSkillDamageCalc(tm:TMap; tc:TChara; ts:TMob; Tick:cardinal);
        procedure SendMSkillAttack(tm:TMap; tc:TChara; ts:TMob; Tick:cardinal; k:integer);
        //procedure MonsterCastTime(tm:Tmap; ts:TMob; Tick:cardinal);

        procedure LoadMonsterAIData(tm:TMap; ts:TMob; Tick:cardinal);
        procedure CalculateSkillIf(tm:TMap; ts:TMob; Tick:cardinal);
        procedure CheckSkill(tm:TMap; ts:TMob; tsAI2:TMobAIDBFusion; Tick:Cardinal);
        procedure NewMonsterCastTime(tm:TMap; ts:TMob; Tick:Cardinal);

        procedure PetAttackSkill(tm:TMap; ts:TMob; tc:TChara);
        procedure PetDamageProcess(tm:TMap; ts:TMob; tc:TChara; Dmg:integer; Tick:cardinal; isBreak:Boolean = True);
        procedure SendPetSkillAttack(tm:TMap; tc:TChara; ts:TMob; Tick:cardinal; SkillID:integer);

        function DamageProcess2(tm:TMap; tc:TChara; tc1:TChara; Dmg:integer; Tick:cardinal; isBreak:Boolean = True) : Boolean;  {Player Attacking Player}
        function DamageProcess3(tm:TMap; ts:TMob; tc1:TChara; Dmg:integer; Tick:cardinal; isBreak:Boolean = True) : Boolean;  {Monster Attacking Player}

var

dmg           :array[0..7] of integer;


implementation


(*-----------------------------------------------------------------------------*
Monster's AI

ChrstphR 2004/04/25 - cleaned up two potential memory leaks
- Exit; called without freeing the TStringList sl that is created in the code.
*-----------------------------------------------------------------------------*)
procedure CalcAI(tm:TMap; ts:TMob; Tick:Cardinal);
var
	j   : Integer;
	i1  : Integer;
	j1  : Integer;
	k1  : Integer;
	tc1 : TChara; //ref only
	ts2 : TMob;   //ref only
	tn  : TNPC;   //ref only
	sl  : TStringList;
	//ref list that is reused *shudder* to hold string indexes and object refs
	//Early exits mean this must be free'd before Exit called.
begin
	//if ts.Data.Loaded = false then TempNewAIProcedures(tm, ts, Tick);

	with ts do begin
		//MobSkillCalc(tm,ts,Tick);

		if (ts.Stat1 <> 0) and (Data.Range1 > 0) then begin
			pcnt := 0;
			Exit;//ChrstphrR 2004/04/25 - safe
		end;

		if (isLeader) and ( (MonsterMob) or ((isSummon) and (SummonMonsterMob)) )then begin
			if (SlaveCount = 0) and (Random(1000) <= 10) then begin
				WFIFOW( 0, $011a);
				WFIFOW( 2, 196);
				WFIFOW( 4, 1);
				WFIFOL( 6, ID);
				WFIFOL(10, ID);
				WFIFOB(14, 1);
				SendBCmd(tm, ts.Point, 15);
				MobSpawn(tm,ts,Tick);
			end;
		end;//if isLeader...

		sl := TStringList.Create;//ChrstphrR - moved closer to first use..
		if (ATarget = 0) then begin

			if isActive then begin
				//sl.Clear; //First use of SL, it's already empty :)
				for j1 := Point.Y div 8 - 2 to Point.Y div 8 + 2 do begin
					for i1 := Point.X div 8 - 2 to Point.X div 8 + 2 do begin
						for k1 := 0 to tm.Block[i1][j1].CList.Count - 1 do begin
							tc1 := tm.Block[i1][j1].CList.Objects[k1] as TChara;
							if (tc1.HP > 0) and (tc1.Hidden = false) and (tc1.Paradise = false) and ((ts.isGuardian <> tc1.GUildID) or (ts.isGuardian = 0)) and (abs(ts.Point.X - tc1.Point.X) <= 10) and (abs(ts.Point.Y - tc1.Point.Y) <= 10) then begin  //edited by The Harbinger -- darkWeiss Version
								if (tc1.Sit <> 1) or (tc1.Option < 64) then begin
									sl.AddObject(IntToStr(tc1.ID), tc1);
								end;
							end;//if
						end;//for k1
					end;//for i1
				end;//for j1

				if sl.Count > 0 then begin
					j := Random(sl.Count);
					ATarget := StrToInt(sl.Strings[j]);
					ARangeFlag := false;
					AData := sl.Objects[j];
					ATick := Tick;
					ARangeFlag := false;

					sl.Free;// Must Free up open local objects before exiting routine
					Exit;//ChrstphrR 2004/04/25 - safe
				end;
			end;

			if (NOT isLooting) AND Data.isLoot then begin

				sl.Clear;
				for j1 := Point.Y div 8 - 2 to Point.Y div 8 + 2 do begin
					for i1 := Point.X div 8 - 2 to Point.X div 8 + 2 do begin
						for k1 := 0 to tm.Block[i1][j1].NPC.Count - 1 do begin
							tn := tm.Block[i1][j1].NPC.Objects[k1] as TNPC;
							if tn.CType <> 3 then Continue;
							if (abs(tn.Point.X - Point.X) <= 10) and (abs(tn.Point.Y - Point.Y) <= 10) then begin
								sl.AddObject(IntToStr(tn.ID), tn);
							end;
						end;
					end;
				end;

				if sl.Count > 0 then begin
					j := Random(sl.Count);
					tn := sl.Objects[j] as TNPC;
					j := SearchPath2(path, tm, Point.X, Point.Y, tn.Point.X, tn.Point.Y);
					if (j <> 0) then begin
						isLooting := True;
						ATarget := tn.ID;
						ATick := Tick;

						pcnt := j;
						ppos := 0;
						MoveTick := Tick;
						tgtPoint := tn.Point;

					end;
					sl.Free;// Must Free up open local objects before exiting routine
					Exit;//ChrstphrR 2004/04/25 - safe
				end;
			end;
		//if ATarget=0 ...
		end else begin //ATarget > 0
			if isLeader AND NOT isLooting then begin
				for j1 := Point.Y div 8 - 2 to Point.Y div 8 + 2 do begin
					for i1 := Point.X div 8 - 2 to Point.X div 8 + 2 do begin
						for k1 := 0 to tm.Block[i1][j1].Mob.Count - 1 do begin
							if (tm.Block[i1][j1].Mob.Objects[k1] is TMob) then begin
								ts2 := tm.Block[i1][j1].Mob.Objects[k1] as TMob;
								if (ts2 <> nil) or (ts2 <> ts) then begin
									if ts2.LeaderID <> ts.ID then continue;
									if (abs(ts.Point.X - ts2.Point.X) <= 10) and (abs(ts.Point.Y - ts2.Point.Y) <= 10) then begin
										if ts2.ATarget = 0 then begin
											ts2.ATarget := ts.ATarget;
											ts2.ARangeFlag := false;
											ts2.AData := ts.AData;
											ts2.ATick := Tick;
											ts2.ARangeFlag := false;
										end;
									end;
								end;
							end;
						end;
					end;
				end;
			end;

			if Data.isLink AND NOT isLooting then begin
				for j1 := Point.Y div 8 - 2 to Point.Y div 8 + 2 do begin
					for i1 := Point.X div 8 - 2 to Point.X div 8 + 2 do begin
						for k1 := 0 to tm.Block[i1][j1].Mob.Count - 1 do begin
							ts2 := tm.Block[i1][j1].Mob.Objects[k1] AS TMob;
							if (ts2 <> nil) or (ts2 <> ts) then begin
								if ts2.JID <> ts.JID then Continue;
								if (abs(ts.Point.X - ts2.Point.X) <= 10) and (abs(ts.Point.Y - ts2.Point.Y) <= 10) then begin
									if ts2.ATarget = 0 then begin
										ts2.ATarget    := ts.ATarget;
										ts2.ARangeFlag := false;
										ts2.AData      := ts.AData;
										ts2.ATick      := Tick;
										ts2.ARangeFlag := false;
									end;
								end;
							end;
						end;//for k1
					end;//for i1
				end;//for j1
			end;//if Data.isLink
		end;//if-else ATarget=0/ATarget>0

		//ChrstphrR - if the 2 early Exit's don't stop the flow, this existing
		//call will free up the StringList before we leave.
		sl.Free;
	end;//with ts
end;(* proc CalcAI()
*-----------------------------------------------------------------------------*)


//------------------------------------------------------------------------------

{Spawn Monster}
procedure MobSpawn(tm:TMap; ts:TMob; Tick:cardinal);
var
	i, j, k, h, m        :integer;
	tc                   :TChara;
  ts1                    :TMob;
  tss                    :TSlaveDB;

begin

//if (MonsterMob = true) then begin
begin
        k := SlaveDBName.IndexOf(ts.Data.Name);
        if (k <> -1) then begin
                ts.isLeader := true;
                tss := SlaveDBName.Objects[k] as TSlaveDB;
                if ts.Data.Name = tss.Name then begin

                        h := tss.TotalSlaves;
                        ts.SlaveCount := h;

                        repeat
                                for i := 0 to 4 do begin
                                        if (tss.Slaves[i] <> -1) and (h <> 0) then begin
                                                ts1 := TMob.Create;
					        ts1.Data := MobDBName.Objects[tss.Slaves[i]] as TMobDB;
					        ts1.ID := NowMobID;
					        Inc(NowMobID);
					        ts1.Name := ts1.Data.JName;
					        ts1.JID := ts1.Data.ID;
                  ts1.LeaderID := ts.ID;
                  ts1.Data.isLink := false;
					        ts1.Map := ts.Map;
                  ts1.Point.X := ts.Point.X + Random(10);
					        ts1.Point.Y := ts.Point.Y + Random(10);
					        ts1.Dir := ts.Dir;
					        ts1.HP := ts1.Data.HP;
                                                if ts.Data.Speed < ts1.Data.Speed then begin
					                ts1.Speed := ts.Data.Speed;
                                                end else begin
                                                        ts1.Speed := ts1.Data.Speed;
                                                end;

					        ts1.SpawnDelay1 := $7FFFFFFF;
					        ts1.SpawnDelay2 := 0;
					        ts1.SpawnType := 0;
					        ts1.SpawnTick := 0;
                                                if ts1.Data.isDontMove then
						        ts1.MoveWait := $FFFFFFFF
					        else
                                                        ts1.MoveWait := timeGetTime();
					        ts1.ATarget := 0;
					        ts1.ATKPer := 100;
					        ts1.DEFPer := 100;
					        ts1.DmgTick := 0;
                                                ts1.Element := ts1.Data.Element;
                                                ts1.isActive := false;

					        for j := 0 to 31 do begin
						        ts1.EXPDist[j].CData := nil;
						        ts1.EXPDist[j].Dmg := 0;
				        	end;

					        if ts1.Data.MEXP <> 0 then begin
						        for j := 0 to 31 do begin
							        ts1.MVPDist[j].CData := nil;
							        ts1.MVPDist[j].Dmg := 0;
						        end;
						        ts1.MVPDist[0].Dmg := ts1.Data.HP * 30 div 100; //FA偵30%壛嶼
					        end;

					        ts1.isSummon := true;
                                                ts1.isSlave := true;
                                                tm.Mob.AddObject(ts1.ID, ts1);
					        tm.Block[ts1.Point.X div 8][ts1.Point.Y div 8].Mob.AddObject(ts1.ID, ts1);

                                                for j := ts1.Point.Y div 8 - 2 to ts1.Point.Y div 8 + 2 do begin
		                                        for m := ts1.Point.X div 8 - 2 to ts1.Point.X div 8 + 2 do begin

			                                        for k := 0 to tm.Block[m][j].CList.Count - 1 do begin
				                                        tc := tm.Block[m][j].CList.Objects[k] as TChara;
				                                        if tc = nil then continue;
                                                                        if (abs(ts1.Point.X - tc.Point.X) < 16) and (abs(ts1.Point.Y - tc.Point.Y) < 16) then begin
					                                        SendMData(tc.Socket, ts1);
                                                                                SendBCmd(tm,ts1.Point,41,tc,False);
				                                        end;
                                                                end;
		                                        end;
	                                        end;
                                                h := h - 1;
                                        end;
                                end;
                        until (h <= 0);

                        end;
                end;
        end;

end;
//------------------------------------------------------------------------------
// Darkhelmet, Ah, my classic AI, i'll leave it here commented out just because
// of good times with it

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -