|
建立在bt大虾的代码之上,实现效果是在看见范围内(角色能移动的范围+可攻击的范围内),对每个点进行价值的判定,选定最有价值的点进行攻击
如果可见范围内没有人,则不会有任何行动,范围外的路径选择,恢复之类的行动请自行编写,或者利用原来bt大虾留下的程序
还有这样的话,仅仅是对攻击方攻击方面进行判定,之后的走位,技能的使用都需要考量,加权方面,是否对除了对伤害,或者对其他的也有加权,抛砖引玉啦,大家有好的想法,代码不要藏啦。。。
构建在原版所有战斗之上,没有很明显的迟钝,延迟- 对了修改了这个函数,加了一句话
- procedure CalCanSelect(bnum, mode: integer);
- var
- i, i1, i2: integer;
- begin
- for i1 := 0 to 63 do
- for i2 := 0 to 63 do
- begin
- Bfield[3, i1, i2] := 0;
- //mode为0表示移动, 这时建筑和有人物(不包括自己)的位置不可选
- if mode = 0 then
- begin
- if Bfield[1, i1, i2] > 0 then Bfield[3, i1, i2] := -1;
- if Bfield[2, i1, i2] >= 0 then Bfield[3, i1, i2] := -1;
- if Bfield[2, i1, i2] = bnum then Bfield[3, i1, i2] := 0;
- end;
- //就是这句,让已经计算过的格子不再计算第2遍
- Bfield[5, i1, i2] := 0;
- end;
- if mode = 0 then
- begin
- SeekPath(Brole[bnum].X, Brole[bnum].Y, Brole[bnum].Step + 2);
- //递归算法的问题, 步数+2参与计算
- for i1 := 0 to 63 do
- for i2 := 0 to 63 do
- begin
- if Bfield[3, i1, i2] > 0 then
- Bfield[3, i1, i2] := 0
- else
- Bfield[3, i1, i2] := 1;
- end;
- end;
- end;
- 主ai程序
- procedure AutoBattle(bnum: integer);
- var
- flag, i, p, temp, a, rnum, inum, eneamount, aim, mnum, level, Ax1, Ay1, Ax2, Ay2, i1, i2, step, step1, dis1, dis0, dis2,dis, temptype,i3,i4: integer;
- str: widestring;
- begin
- //找寻可攻击范围内,攻击价值最高的点,并攻击
- //判断是否可以攻击
- if (Brole[bnum].Acted = 0) and (rrole[rnum].PhyPower >= 10) then
- begin
- flag := 0;//移动方式的判断位,以及是否有好的攻击点的判断位
- temp := 0;
- Ax2 := 0;
- Ay2 := 0;
- Ax1 := 0;
- Ay1 := 0;
- Ax := Bx;
- Ay := By;
- for i := 0 to 9 do
- begin
- mnum := Rrole[rnum].Magic[ i ];
- if mnum > 0 then
- begin
- level := Rrole[rnum].MagLevel[ i ] div 100 + 1;
- if level <= 0 then level := 1;
- if level > 10 then level := 10;
- if (rmagic[mnum].HurtType = 0) then
- begin
- //判断面/点攻最大伤害的点
- //如果您的角色是个超级人物,或许在这一步遍历会有点卡,我有个建议,就是判断方向,四个象限往一个方向会好一点
- //或者是选定一个大概范围遍历(人多的地方),这个函数我有一些构思,没有着手写,需要的话,m我要好了
- //类似于一个遍历,在他周围一定范围内的人数计下来,再计算范围内最边缘角色的x,y的目标
- //在底下计算价值的时候,就在这个范围计算了
- if (rmagic[mnum].AttAreaType = 3) or (rmagic[mnum].AttAreaType = 0)then
- begin
- dis1 := Brole[bnum].Step;
- CalCanSelect(bnum, 0);
- for i1 := max(Bx-dis1, 0) to min(Bx+dis1, 63) do
- for i2 := max(By-dis1, 0) to min(By+dis1, 63) do
- begin
- if Bfield[3, i1, i2] = 0 then
- begin
- dis0 := rmagic[mnum].MoveDistance[level - 1];
- for i3 := max(i1-dis0, 0) to min(i1+dis0, 63) do
- for i4 := max(i2-dis0, 0) to min(i2+dis0, 63) do
- begin
- Ax := i3;
- Ay := i4;
- dis2 := abs( i1 - i3 )+abs( i2 - i4 );
- if (temp<=AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i3, i4] = 0) and (dis2 <= dis0)then
- begin
- Ax2 := i1;
- Ay2 := i2;
- Ax1 := i3;
- Ay1 := i4;
- temp:=AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 1;
- end;
- Bfield[5, i3, i4] := 1;
- end;
- end;
- end;
- end
- //十字攻的判断
- else if (rmagic[mnum].AttAreaType = 2) then
- begin
- dis1 := Brole[bnum].Step;
- CalCanSelect(bnum, 0);
- for i1 := max(Bx-dis1, 0) to min(Bx+dis1, 63) do
- for i2 := max(By-dis1, 0) to min(By+dis1, 63) do
- begin
- if Bfield[3, i1, i2] = 0 then
- begin
- Ax := i1;
- Ay := i2;
- if (temp <= AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i1, i2] = 0)then
- begin
- Ax1 := i1;
- Ay1 := i2;
- temp := AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 2;
- end;
- Bfield[5, i1, i2] := 1;
- end;
- end;
- end
- //线攻的判断
- else if (rmagic[mnum].AttAreaType = 1) then
- begin
- dis1 := Brole[bnum].Step;
- CalCanSelect(bnum, 0);
- for i1 := max(Bx-dis1, 0) to min(Bx+dis1, 63) do
- for i2 := max(By-dis1, 0) to min(By+dis1, 63) do
- begin
- if Bfield[3, i1, i2] = 0 then
- begin
- //x+1
- Ax := i1+1;
- Ay := i2;
- if (temp <= AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i1, i2] = 0) then
- begin
- Ax1 := i1;
- Ay1 := i2;
- temp:=AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 3;
- end;
- //x-1
- Ax := i1-1;
- Ay := i2;
- if (temp <= AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i1, i2] = 0) then
- begin
- Ax1 := i1;
- Ay1 := i2;
- temp:=AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 4;
- end;
- //y+1
- Ax := i1;
- Ay := i2+1;
- if (temp <= AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i1, i2] = 0) then
- begin
- Ax1 := i1;
- Ay1 := i2;
- temp:=AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 5;
- end;
- //y-1
- Ax := i1;
- Ay := i2-1;
- if (temp <= AutoManyDamage(bnum, i, i1, i2)) and (AutoManyDamage(bnum, i, i1, i2) <> 0) and (Bfield[5, i1, i2] = 0) then
- begin
- Ax1 := i1;
- Ay1 := i2;
- temp:=AutoManyDamage(bnum, i, i1, i2);
- p := i;
- flag := 6;
- end;
- Bfield[5, i1, i2] := 1;
- end;
- end;
- end
- end;
- end;
- end;
- //动
- if(flag <> 0) then
- begin
- //点面攻的移动方式
- if(flag = 1) then
- begin
- Ax := Ax2;
- Ay := Ay2;
- MoveAmination(bnum);
- Ax := Ax1;
- Ay := Ay1;
- end
- //十字
- else if(flag = 2) then
- begin
- Ax := Ax1;
- Ay := Ay1;
- MoveAmination(bnum);
- Ax := Bx;
- Ay := By;
- end
- //线
- else if (flag >= 3) then
- begin
- Ax := Ax1;
- Ay := Ay1;
- MoveAmination(bnum);
- if(flag = 3) then
- begin
- Ax := Bx + 1;
- Ay := By;
- end
- else if(flag = 4) then
- begin
- Ax := Bx - 1;
- Ay := By;
- end
- else if(flag = 5) then
- begin
- Ax := Bx;
- Ay := By + 1;
- end
- else if(flag = 6) then
- begin
- Ax := Bx;
- Ay := By - 1;
- end;
- end;
- //攻击
- AutoAttack(bnum, p);
- end;
- end;
- end;
- 以下是用到的一些函数
- //计算周围某个点所造成的总价值,从攻击函数进行改写
- function AutoManyDamage(bnum, mnum1, Bx1, By1: integer): integer;
- var
- i1, i2, step, step1, Ax1, Ay1, dis, rnum, mnum, level: integer;
- begin
- rnum := brole[bnum].rnum;
- mnum := Rrole[rnum].Magic[mnum1];
- level := Rrole[rnum].MagLevel[mnum1] div 100 + 1;
- if level > 10 then level := 10;
- if level <= 0 then level := 1;
- result :=0;
- step := rmagic[mnum].MoveDistance[level - 1];
- step1 := 0;
- if rmagic[mnum].AttAreaType = 3 then step1 := rmagic[mnum].AttDistance[level - 1];
- if abs(Ax - Bx1) + abs(Ay - By1) <= step + step1 then
- begin
- if (rmagic[mnum].AttAreaType = 3) then
- begin
- dis := 0;
- Ax1 := Bx1;
- Ay1 := By1;
- for i1 := min(Ax, Bx1) to max(Ax, Bx1) do
- for i2 := min(Ay, By1) to max(Ay, By1) do
- begin
- if (abs(i1 - Ax) <= step1) and (abs(i2 - Ay) <= step1) and (abs(i1 - Bx1) + abs(i2 - By1) <= step + step1) then
- begin
- if dis < abs(i1 - Bx1) + abs(i2 - By1) then
- begin
- dis := abs(i1 - Bx1) + abs(i2 - By1);
- Ax1 := i1;
- Ay1 := i2;
- end;
- end;
- end;
- Ax := Ax1;
- Ay := Ay1;
- end;
- if Rmagic[mnum].AttAreaType <> 3 then
- GetAminationPosition(Rmagic[mnum].AttAreaType, step, Bx1, By1)
- else
- GetAminationPosition(Rmagic[mnum].AttAreaType, step1, Bx1, By1);
- for i1 := 0 to sign(Rrole[rnum].AttTwice) do
- begin
- result :=CalAllDamage(bnum, mnum, level);
- end;
- end;
- end;
- //计算利用该技能在选中点能造成的总价值,从计算伤害改来
- function CalAllDamage(bnum, mnum, level: integer): integer;
- var
- i, i1, rnum, temp: integer;
- begin
- rnum := brole[bnum].rnum;
- if RRole[rnum].CurrentMP < rmagic[mnum].NeedMP * ((level + 1) div 2) then level := RRole[rnum].CurrentMP div rmagic[mnum].NeedMP * 2;
- if level > 10 then level := 10;
- result :=0;
- for i := 0 to broleamount - 1 do
- begin
- if (Bfield[4, Brole[ i ].X, Brole[ i ].Y] <> 0) and (Brole[bnum].Team <> Brole[ i ].Team) and (Brole[ i ].Dead = 0) then
- begin
- //生命伤害
- if (rmagic[mnum].HurtType = 0) then
- begin
- temp :=0;
- //计算左右
- //注意!!会左右的人会对同一个会杀死的目标,计算双倍加权
- for i1 := 0 to sign(Rrole[rnum].AttTwice) do
- begin
- temp := CalHurtValue(bnum, i, mnum, level)+temp;
- end;
- //看看有没有人会死奖励价值10000
- if (temp > Rrole[Brole[i].rnum].CurrentHP) then
- begin
- result := result + 10000//奖励10000点价值 〉1个人9999的血上限
- end;
- //CalHurtValue(bnum, i, mnum, level),这个函数一般大虾都喜欢把命中判定放在这里判断
- //但是如果在这里判断,我以为,是不是加权太高了,包括上面杀死目标的判定时
- //当然最后的加权肯定是大家自己选择的
- result := result + CalHurtValue(bnum, i, mnum, level);//加权公式,请自行对ai的加权进行判定
- end;
- {基于内力的aoe,还没有打算开始在ai中使用,这段还是编者自己做吧
- //内力伤害
- if (rmagic[mnum].HurtType = 1) then
- begin
- hurt := rmagic[mnum].HurtMP[level - 1];
- if hurt > Rrole[Brole[i].rnum].CurrentMP then hurt := Rrole[Brole[i].rnum].CurrentMP;
- Brole[i].ShowNumber := hurt;
- Rrole[Brole[i].rnum].CurrentMP := Rrole[Brole[i].rnum].CurrentMP - hurt;
- //增加己方内力及最大值
- if hurt < rmagic[mnum].AddMP[level - 1] then RRole[rnum].CurrentMP := RRole[rnum].CurrentMP + hurt;
- if hurt >= rmagic[mnum].AddMP[level - 1] then RRole[rnum].CurrentMP := RRole[rnum].CurrentMP + rmagic[mnum].AddMP[level - 1];
- Brole[bnum].ExpGot := Brole[bnum].ExpGot + hurt div 20;
- //RRole[rnum].MaxMP := RRole[rnum].MaxMP + random(hurt div 2);
- //if RRole[rnum].MaxMP > MAX_MP then RRole[rnum].MaxMP := MAX_MP;
- if RRole[rnum].CurrentMP > RRole[rnum].MaxMP then RRole[rnum].CurrentMP := RRole[rnum].MaxMP;
- //中毒
- addpoi := rrole[rnum].AttPoi + rmagic[mnum].Poision * level - rrole[Brole[ i ].rnum].DefPoi;
- if rrole[Brole[ i ].rnum].Poision < 0 then rrole[Brole[ i ].rnum].Poision := 0;
- if addpoi + rrole[Brole[ i ].rnum].Poision > 99 then addpoi := 99 - rrole[Brole[ i ].rnum].Poision;
- if addpoi < 0 then addpoi := 0;
- if rrole[Brole[ i ].rnum].DefPoi >= 99 then addpoi := 0;
- rrole[Brole[ i ].rnum].Poision := rrole[Brole[ i ].rnum].Poision + addpoi;
- end; }
- end;
- end;
- end;
- //假装设定攻击范围,从设定攻击范围改来
- procedure GetAminationPosition(mode, step, Bx1, By1: integer);
- var
- i, i1, i2: integer;
- begin
- for i1 := 0 to 63 do
- for i2 := 0 to 63 do
- begin
- Bfield[4, i1, i2] := 0;
- //按攻击类型判断是否在范围内
- case mode of
- 0:
- begin
- if (i1 = Ax) and (i2 = Ay) then Bfield[4, i1, i2] := 1;
- end;
- 3:
- begin
- if (abs(i1 - Ax) <= step) and (abs(i2 - Ay) <= step) then Bfield[4, i1, i2] := 1;
- end;
- 1:
- begin
- if ((i1 = Bx1) or (i2 = By1)) and (sign(Ax - Bx1) = sign(i1 - Bx1)) and (abs(i1 - Bx1) <= step) and (sign(Ay - By1) = sign(i2 - By1)) and (abs(i2 - By1) <= step) then
- Bfield[4, i1, i2] := 1;
- end;
- 2:
- begin
- if ((i1 = Bx1) and (abs(i2 - By1) <= step)) or ((i2 = By1) and (abs(i1 - Bx1) <= step)) then
- Bfield[4, i1, i2] := 1;
- if ((i1 = Bx1) and (i2 = By1)) then Bfield[4, i1, i2] := 0;
- end;
- end;
- end;
- end;
- //攻击
- procedure AutoAttack(bnum, mnum1: integer);
- var
- i1, i2, step, step1, Ax1, Ay1,dis,rnum,mnum,level: integer;
- begin
- rnum := brole[bnum].rnum;
- mnum := Rrole[rnum].Magic[mnum1];
- level := Rrole[rnum].MagLevel[mnum1] div 100 + 1;
- if level > 10 then level := 10;
- if level <= 0 then level := 1;
- step := rmagic[mnum].MoveDistance[level - 1];
- step1 := 0;
- if rmagic[mnum].AttAreaType = 3 then step1 := rmagic[mnum].AttDistance[level - 1];
- if abs(Ax - Bx) + abs(Ay - By) <= step + step1 then
- begin
- //step := Rmagic[mnum, 28+level-1];
- if (rmagic[mnum].AttAreaType = 3) then
- begin
- //step1 := Rmagic[mnum, 38+level-1];
- dis := 0;
- Ax1 := Bx;
- Ay1 := By;
- for i1 := min(Ax, Bx) to max(Ax, Bx) do
- for i2 := min(Ay, By) to max(Ay, By) do
- begin
- if (abs(i1 - Ax) <= step1) and (abs(i2 - Ay) <= step1) and (abs(i1 - Bx) + abs(i2 - By) <= step + step1) then
- begin
- if dis < abs(i1 - Bx) + abs(i2 - By) then
- begin
- dis := abs(i1 - Bx) + abs(i2 - By);
- Ax1 := i1;
- Ay1 := i2;
- end;
- end;
- end;
- Ax := Ax1;
- Ay := Ay1;
- end;
- if Rmagic[mnum].AttAreaType <> 3 then
- SetAminationPosition(Rmagic[mnum].AttAreaType, step)
- else
- SetAminationPosition(Rmagic[mnum].AttAreaType, step1);
- Brole[bnum].Acted := 1;
- for i1 := 0 to sign(Rrole[rnum].AttTwice) do
- begin
- Rrole[rnum].MagLevel[mnum] := Rrole[rnum].MagLevel[mnum] + random(2) + 1;
- if Rrole[rnum].MagLevel[mnum] > 999 then Rrole[rnum].MagLevel[mnum] := 999;
- if rmagic[mnum].UnKnow[4] > 0 then callevent(rmagic[mnum].UnKnow[4])
- else AttackAction(bnum, mnum, level);
- end;
- end;
- end;
复制代码 |
|