战网中国

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2645|回复: 17

【D2BS】以kolbot为基础的城内绕路踢桶的一种思路(穷举)

[复制链接]

4

主题

44

帖子

260

积分

侠客

Rank: 3Rank: 3

积分
260
发表于 2019-1-1 15:24:25 | 显示全部楼层 |阅读模式
本帖最后由 loveqiao361 于 2019-1-9 13:16 编辑

我的本意是让kolbot在城内完美运行,解决所有情况,总体思路如下:路
根据地图类型,当前地点与目标地点这3个变量,判断返回给执行移动的路线是否可行;
如果默认寻路方式可行,则返回0,不可行,则通过3个变量分不同情况返回自定义路线,并在路线的每个坐标节点(除目标地点坐标)上设置执行踢桶。

由于自定义路线需穷举,工程量较大,导致code比较冗长,本人接触JS也不是很久,还望前辈们指点。

首先要分析清楚town.js中城内寻路的逻辑。
修改moveToSpot这个function,作出如下修改,改变path的获取方式。
  1.         moveToSpot: function (spot) {  
  2.                 var i, path = this.getMyPath(spot),
  3.                     townSpot = this.act[me.act - 1].spot[spot];

  4.                         if(path === 0){
  5.                                 for (i = 0; i < townSpot.length; i += 2) {
  6.                                         if (getDistance(me, townSpot[i], townSpot[i + 1]) > 2) {
  7.                                         Pather.moveTo(townSpot[i], townSpot[i + 1], 3, false, true);
  8.                                         }
  9.                                         switch (spot) {
  10.                                                 case "stash":
  11.                                                         if (!!getUnit(2, 267)) {
  12.                                                                 return true;
  13.                                                         }

  14.                                                         break;
  15.                                                 case "cain":
  16.                                                         if (!!getUnit(1, NPC.Cain)) {
  17.                                                                 return true;
  18.                                                         }

  19.                                                         break;
  20.                                                 case "palace":
  21.                                                         if (!!getUnit(1, "jerhyn")) {
  22.                                                                 return true;
  23.                                                         }

  24.                                                         break;
  25.                                                 case "portalspot":
  26.                                                 case "sewers":
  27.                                                         if (getDistance(me, townSpot[i], townSpot[i + 1]) < 10) {
  28.                                                                 return true;
  29.                                                         }

  30.                                                         break;
  31.                                                 case "waypoint":
  32.                                                         if (!!getUnit(2, "waypoint")) {
  33.                                                                 return true;
  34.                                                         }

  35.                                                         break;
  36.                                                 default:
  37.                                                         if (!!getUnit(1, spot)) {
  38.                                                                 return true;
  39.                                                         }
  40.                                                         break;
  41.                                         }
  42.                                 }
  43.                         }else {
  44.                         for(i = 0; i < path.length; i += 1){
  45.                                 Pather.moveTo(path[i].x, path[i].y);
  46.                                 if (i+1 !== path.length){
  47.                                 this.openChestsInTown(5);
  48.                                 }
  49.                         }
  50.                         }
  51.                         
  52.                         switch (spot) {
  53.                         case "stash":
  54.                                 if (!!getUnit(2, 267)) {
  55.                                         return true;
  56.                                 }

  57.                                 break;
  58.                         case "cain":
  59.                                 if (!!getUnit(1, NPC.Cain)) {
  60.                                         return true;
  61.                                 }

  62.                                 break;
  63.                         case "palace":
  64.                                 if (!!getUnit(1, "jerhyn")) {
  65.                                         return true;
  66.                                 }

  67.                                 break;
  68.                         case "portalspot":
  69.                         case "sewers":
  70.                                 if (getDistance(me, townSpot[0], townSpot[1]) < 10) {
  71.                                         return true;
  72.                                 }

  73.                                 break;
  74.                         case "waypoint":
  75.                                 if (!!getUnit(2, "waypoint")) {
  76.                                         return true;
  77.                                 }

  78.                                 break;
  79.                         default:
  80.                                 if (!!getUnit(1, spot)) {
  81.                                         return true;
  82.                                 }

  83.                                 break;
  84.                         }

  85.                 return false;
  86.         },
复制代码
建立getMyPath这个function,判断3个变量返回路线,由于所有情况代码过多,这里只贴出一种地图类型作为例子。
  1.         getMyPath: function (spot) {
  2.                 var path, defaultpath = 0, fire, wp, myspot, townmode, townspot,
  3.                         direction = [];

  4.                 if (!this.act[me.act - 1].hasOwnProperty("townmode") || !this.act[me.act - 1].hasOwnProperty("spot") || !this.act[me.act - 1].spot.hasOwnProperty(spot)) {
  5.                         return false;
  6.                 }

  7.                 if (!typeof (this.act[me.act - 1].spot[spot]) === "object" || !typeof (this.act[me.act - 1].townmod) === "string") {
  8.                         return false;
  9.                 }
  10.                
  11.                 myspot = this.getMySpot();
  12.                 townmode = this.act[me.act - 1].townmode;
  13.                
  14.                 if(me.act===1){
  15.                 fire = this.act[me.act-1].spot.fire;        
  16.                 }
  17.                
  18.                 townspot = this.act[me.act - 1].spot[spot];

  19.                 /**example
  20.                 if(myspot === "" && townmode === "" && spot === ""){
  21.                         return [{x:, y:},{x:, y:},{x:, y:},{x:, y:}];
  22.                 }
  23.                 if(myspot === "" && townmode === "" && spot === ""){
  24.                         return defaultpath;
  25.                 }
  26.                 */
  27.                 switch (townmode){
  28.                         case "1a":
  29.                         //Initialspot1 Initialspot1b
  30.                         //wp
  31.                         if(spot === "waypoint"){
  32.                                 if(myspot === "Charsi"){ //all
  33.                                         return defaultpath;
  34.                                 }
  35.                                 return [{x:fire[0]-2, y:fire[1]-19},{x:townspot[0], y:townspot[1]}];
  36.                         }
  37.                         //portalspot
  38.                         if(spot === "portalspot"){
  39.                                 if(myspot === "Charsi"){ //no waypoint
  40.                                 return [{x:fire[0]-9, y:fire[1]-29},{x:fire[0], y:fire[1]-10},{x:townspot[0], y:townspot[1]}];
  41.                                 }

  42.                         }
  43.                         //between tasks
  44.                         /**Akara
  45.                         if(spot === "akara"){
  46.                                 if(myspot === ""){ //Initialspot1  portalspot1
  47.                                        
  48.                                 }
  49.                         
  50.                         }
  51.                         */
  52.                         //Charsi
  53.                         if(spot === "charsi"){
  54.                                 if(myspot === "portalspot1" || "Akara"){ //Initialspot1  portalspot1 Akara
  55.                                 return [{x:fire[0]-2, y:fire[1]-19},{x:fire[0]-9, y:fire[1]-29},{x:townspot[0], y:townspot[1]}];
  56.                                 }
  57.                         
  58.                         }
  59.                         //Gheed
  60.                         if(spot === "gheed"){
  61.                                 if(myspot === "Charsi"){ //Initialspot1  portalspot1 Akara Charsi
  62.                                 return [{x:fire[0]-9, y:fire[1]-29},{x:fire[0], y:fire[1]-10},{x:townspot[0], y:townspot[1]}];
  63.                                 }
  64.                         
  65.                         }
  66.                         //Kashya
  67.                         if(spot === "kashya"){
  68.                                 if(myspot === "Charsi"){ //Initialspot1  portalspot1 Akara Charsi Gheed
  69.                                 return [{x:fire[0]-9, y:fire[1]-29},{x:fire[0], y:fire[1]-10},{x:townspot[0], y:townspot[1]}];
  70.                                 }
  71.                         
  72.                         }
  73.                         //Stash
  74.                         if(spot === "stash"){
  75.                                 if(myspot === "Charsi"){ //Initialspot1  portalspot1 Akara Charsi Gheed Kashya
  76.                                 return [{x:fire[0]-9, y:fire[1]-29},{x:fire[0], y:fire[1]-10},{x:townspot[0], y:townspot[1]}];
  77.                                 }
  78.                         
  79.                         }
  80.                         
  81.                         break;
  82.                 }
  83.                
  84.                 //default path
  85.                 return defaultpath;

  86.         },
复制代码
OpenChestsInTown这个函数就不作过多解释了,参考Misc中的OpenChests即可。

上面可以看到,townspot这个变量是从act对象取出的,因为我修改了initialize这个function,
以A1为例,
在this.act[0].initialized = true;这一行上方加上
this.act[0].townmode = this.getTownMode();

于是再建立getTownMode这个funciton,由于执行initialize的情况的地点只有出生点、小站和城内回城门。
所以根据当前自身地点来进行不同形式的地图类型判断,这里同样只给出act1的例子。
  1.         getTownMode: function () {        
  2.         var        fire, fireUnit, myspot = this.getMySpot();

  3.                 switch(myspot){
  4.                         //act 1
  5.                         case "Initialspot1":
  6.                         fireUnit = getPresetUnit(1, 2, 39);
  7.                         if (!fireUnit) {
  8.                                 return false;
  9.                         }
  10.                         fire = [fireUnit.roomx * 5 + fireUnit.x, fireUnit.roomy * 5 + fireUnit.y];                        
  11.                         
  12.                                 if(this.checkUnit(2, "barrel", fire[0]-5 ,fire[1]-22) === 1){
  13.                                         return "1a";
  14.                                 }else if(this.checkUnit(2, "roguecorpse", fire[0]-11 ,fire[1]-28) === 1){
  15.                                         return "1c";
  16.                                 }else {
  17.                                         return "1d";
  18.                                 }
  19.                         break;
  20.                         
  21.                         case "Initialspot1b":
  22.                                         return "1b";
  23.                         break;
  24.                         
  25.                         case "portalspot1":
  26.                         fireUnit = getPresetUnit(1, 2, 39);
  27.                         if (!fireUnit) {
  28.                                 return false;
  29.                         }
  30.                         fire = [fireUnit.roomx * 5 + fireUnit.x, fireUnit.roomy * 5 + fireUnit.y];        
  31.                         
  32.                                 Pather.moveTo(fire[0]-9, fire[1]-9);
  33.                                 if(this.checkUnit(2, "barrel", fire[0]-5 ,fire[1]-22) === 1){
  34.                                         return "1a";
  35.                                 }else if (this.checkUnit(2, "roguecorpse", fire[0]+7 ,fire[1]-32) === 1){
  36.                                         return "1b";
  37.                                 }else if(this.checkUnit(2, "roguecorpse", fire[0]-11 ,fire[1]-28) === 1){
  38.                                         return "1c";
  39.                                 }else {
  40.                                         return "1d";
  41.                                 }
  42.                         break;
  43.                 }
  44.                
  45.                 return false;
  46.         },
复制代码


然后建立getMySpot函数,通过比较me坐标与各类spot、出生点point坐标距离,返回一个最近的坐标,再根据坐标返回字符串来判断当前的人物位置,同样给出act1的。
  1.         getMySpot: function () {
  2.                 var myspot,
  3.                         spotpointList = [];
  4.                         
  5.                 switch (me.act) {
  6.                         case 1:
  7.                         var fire, wp, fireUnit;
  8.                                 wp = getPresetUnit(1, 2, 119),
  9.                                 fireUnit = getPresetUnit(1, 2, 39);

  10.                         if (!fireUnit) {
  11.                                 return false;
  12.                         }

  13.                         fire = [fireUnit.roomx * 5 + fireUnit.x, fireUnit.roomy * 5 + fireUnit.y];
  14.                         
  15.                         spotpointList.push([fire[0] - 9, fire[1] - 9]);//Initialspot1
  16.                         spotpointList.push([fire[0] - 4, fire[1] - 14]);//Initialspot1b
  17.                         spotpointList.push([fire[0] - 7, fire[1] - 12]);//stash
  18.                         spotpointList.push([fire[0] - 5, fire[1] - 2]);//warriv
  19.                         spotpointList.push([fire[0] + 6, fire[1] - 5]);//cain
  20.                         spotpointList.push([fire[0] + 14, fire[1] - 4]);//Kashya
  21.                         spotpointList.push([fire[0] + 56, fire[1] - 30]);//        Akara
  22.                         spotpointList.push([fire[0] - 39, fire[1] - 25]);//Charsi
  23.                         spotpointList.push([fire[0] - 34, fire[1] + 36]);//Gheed
  24.                         spotpointList.push([fire[0] + 10, fire[1] + 18]);//portalspot1
  25.                         spotpointList.push([wp.roomx * 5 + wp.x, wp.roomy * 5 + wp.y]);//waypoint1
  26.                         
  27.                         
  28.                         break;
  29.                         }
  30.                
  31.                
  32.                         spotpointList.sort(Sort.points);
  33.                         myspot = spotpointList[0];
  34.                
  35.                         //Act1        
  36.                         if(me.act === 1){
  37.                                 
  38.                                 var fire, wp, fireUnit;
  39.                                 wp = getPresetUnit(1, 2, 119),
  40.                                 fireUnit = getPresetUnit(1, 2, 39);

  41.                                 if (!fireUnit) {
  42.                                 return false;
  43.                                 }

  44.                                 fire = [fireUnit.roomx * 5 + fireUnit.x, fireUnit.roomy * 5 + fireUnit.y];
  45.                                 
  46.                         if (myspot[0] === fire[0] - 9 && myspot[1] === fire[1] - 9){
  47.                                 return "Initialspot1";
  48.                         }
  49.                         if (myspot[0] === fire[0] - 4 && myspot[1] === fire[1] - 14){
  50.                                 return "Initialspot1b";
  51.                         }
  52.                         if (myspot[0] === fire[0] - 7 && myspot[1] === fire[1] - 12){
  53.                                 return "stash";
  54.                         }
  55.                         if (myspot[0] === fire[0] - 5 && myspot[1] === fire[1] - 2){
  56.                                 return "warriv";
  57.                         }
  58.                         if (myspot[0] === fire[0] + 6 && myspot[1] === fire[1] - 5){
  59.                                 return "cain";
  60.                         }
  61.                         if (myspot[0] === fire[0] + 14 && myspot[1] === fire[1] - 4){
  62.                                 return "Kashya";
  63.                         }
  64.                         if (myspot[0] === fire[0] + 56 && myspot[1] === fire[1] - 30){
  65.                                 return "Akara";
  66.                         }
  67.                         if (myspot[0] === fire[0] - 39 && myspot[1] === fire[1] - 25){
  68.                                 return "Charsi";
  69.                         }
  70.                         if (myspot[0] === fire[0] - 34 && myspot[1] === fire[1] + 36){
  71.                                 return "Gheed";
  72.                         }
  73.                         if (myspot[0] === fire[0] + 10 && myspot[1] === fire[1] + 18){
  74.                                 return "portalspot1";
  75.                         }
  76.                         if (myspot[0] === wp.roomx * 5 + wp.x && myspot[1] === wp.roomy * 5 + wp.y){
  77.                                 return "waypoint1";
  78.                         }
  79.                         return false;

  80.         },
复制代码
附上checkUnit这个function:
  1.         checkUnit: function (type, name, x, y) {
  2.                 var unit;
  3.                 if(type){
  4.                         type = 2;
  5.                 }        
  6.                 if(!name){
  7.                         name = "barrel";
  8.                 }               
  9.                 if(!x || !y){
  10.                         return false;
  11.                 }
  12.                 unit = getUnit(type);
  13.                 if(unit) {
  14.                         do{
  15.                                 if(unit.name && getDistance(x, y, unit.x, unit.y) < 2 && unit.name.toLowerCase() === name) {
  16.                                         return 1;
  17.                                 }
  18.                         }while(unit.getNext());
  19.                         return 0;
  20.                 }
  21.                 return false;
  22.         },        
复制代码



最后以防万一,在doChores这个Function中,this.heal();这一行上面加上:
  1.                 if (!this.act[me.act - 1].initialized) {
  2.                         this.initialize();
  3.                         print("townmode: "+this.act[me.act-1].townmode);
  4.                 }
复制代码

【2019-1-6更新】
由于initNPC的机制,上述方法对于较近的NPC还是会有问题,故将initinitNPC这个function下的
  1.                 if (!npc) {
  2.                         npc = getUnit(1, this.tasks[me.act - 1][task]);

  3.                         if (!npc) {
  4.                                 this.move(this.tasks[me.act - 1][task]);

  5.                                 npc = getUnit(1, this.tasks[me.act - 1][task]);
  6.                         }
  7.                 }
复制代码

改为:
  1.                 if (!npc) {
  2.                         this.move(this.tasks[me.act - 1][task]);

  3.                         npc = getUnit(1, this.tasks[me.act - 1][task]);
  4.                 }
复制代码

这样就会在访问任何NPC时使用Town.move这个function进行我们设定的路线并踢桶了。

这样就完成了,经测试完美解决所有绕路及踢桶情况。




回复

使用道具 举报

118

主题

1404

帖子

4760

积分

精灵王

Rank: 6Rank: 6

积分
4760

社区居民忠实会员原创写手

QQ
发表于 2019-1-1 15:59:47 | 显示全部楼层
又一大神出现..顶一下
回复 支持 反对

使用道具 举报

4

主题

44

帖子

260

积分

侠客

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2019-1-1 16:30:10 来自手机 | 显示全部楼层
getTownMod函数下的checkUnit忘记贴了,随后补上,原理和Misc中的openChest也差不多。
回复 支持 反对

使用道具 举报

1

主题

89

帖子

1490

积分

精灵王

Rank: 6Rank: 6

积分
1490

社区居民忠实会员

发表于 2019-1-1 17:03:09 | 显示全部楼层
哇~有大神出現~ 請問一下~私服自動打火6BOSS點位會隨機出現,導致無法尋找到6BOSS,這點能解嗎?
回复 支持 反对

使用道具 举报

4

主题

44

帖子

260

积分

侠客

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2019-1-1 21:46:53 | 显示全部楼层
viv2553 发表于 2019-1-1 17:03
哇~有大神出現~ 請問一下~私服自動打火6BOSS點位會隨機出現,導致無法尋找到6BOSS,這點能解嗎?
...

OrgTorch.js中尋找6BOSS的方法:
  1.                 case 133: // Matron's Den
  2.                         Precast.doPrecast(true);
  3.                         Pather.moveToPreset(133, 2, 397, 2, 2);
  4.                         Attack.kill(707);
复制代码

說明是通過Preset ID來判斷6BOSS坐標再進行移動的。
通过私服補丁的MPQ文件,找到6BOSS的對應Preset ID,進行更改即可。
回复 支持 反对

使用道具 举报

1

主题

89

帖子

1490

积分

精灵王

Rank: 6Rank: 6

积分
1490

社区居民忠实会员

发表于 2019-1-2 17:40:59 | 显示全部楼层
loveqiao361 发表于 2019-1-1 21:46
OrgTorch.js中尋找6BOSS的方法:

說明是通過Preset ID來判斷6BOSS坐標再進行移動的。

還是不明白,如果可以!要請大神幫忙解謎更清楚一點...
回复 支持 反对

使用道具 举报

0

主题

17

帖子

724

积分

圣骑士

Rank: 5Rank: 5

积分
724

社区居民

发表于 2019-1-4 20:14:27 | 显示全部楼层
厉害厉害
回复

使用道具 举报

4

主题

44

帖子

260

积分

侠客

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2019-1-10 11:16:07 | 显示全部楼层
viv2553 发表于 2019-1-2 17:40
還是不明白,如果可以!要請大神幫忙解謎更清楚一點...

如果是原生kolbot的话,进入房间按pause,手动跑到BOSS边上,按Numpad9在console里看一下presetUnitID,以Matron's Den为例:
  1.                 case 133: // Matron's Den
  2.                         Precast.doPrecast(true);
  3.                         Pather.moveToPreset(133, 2, 397, 2, 2);
  4.                         Attack.kill(707);
复制代码

替换397为console中的PresetUnitID即可
回复 支持 反对

使用道具 举报

1

主题

89

帖子

1490

积分

精灵王

Rank: 6Rank: 6

积分
1490

社区居民忠实会员

发表于 2019-1-11 12:17:50 | 显示全部楼层
loveqiao361 发表于 2019-1-10 11:16
如果是原生kolbot的话,进入房间按pause,手动跑到BOSS边上,按Numpad9在console里看一下presetUnitID,以 ...

每次開房boss的位置都不一樣 ,所以更換位置恐怕沒辦法解決
回复 支持 反对

使用道具 举报

4

主题

44

帖子

260

积分

侠客

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2019-1-11 16:04:01 | 显示全部楼层
viv2553 发表于 2019-1-11 12:17
每次開房boss的位置都不一樣 ,所以更換位置恐怕沒辦法解決

那总有固定几种位置吧,找到对应presetunit id遍历寻找
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|BattleCN ( 陕ICP备05006600号 )

GMT+8, 2019-7-22 11:30 , Processed in 0.050952 second(s), 11 queries , Apc On.

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表