📄 mbm_mlmap.d2l
字号:
this.LastError = ("mlMap.FindPath - The start coord's are not walkable");
return false;
}
if(!_isinrange(_dx, _dy))
{
mlprint("mlMap.FindSorcPath - The end coord's are out of range");
this.LastError = ("mlMap.FindPath - The end coord's are out of range");
return false;
}
if(!this.IsWalkable(_dx, _dy)) {
var temp = this.FindClosestWalkable(_dx,_dy);
_dx = temp.x;
_dy = temp.y;
}
// {
// mlprint("mlMap.FindPath - The end coord's are not walkable");
// this.LastError = ("mlMap.FindPath - The end coord's are not walkable");
// return false;
// }
if(typeof(_err) != "number" || _err < 0) _err = 0;
if(typeof(_dstep) != "number" || _dstep < 1) _dstep = 1;
if(typeof(_rstep) != "number" || _rstep < 1) _rstep = 1;
if(typeof(_err) != "number" || _err < 0) _err = 0;
if(typeof(_algo) != "number" || _algo < 0 || _algo > 1) _algo=0;
if(_algo) {
var oq = new oFIFO();
}
else var oq = new oHeap("h", mlHEAPLOW);
var minx = this.minx;
var miny = this.miny;
var maxx = this.maxx;
var maxy = this.maxy;
var width = this.maxx - this.minx-1;
var height = this.maxy - this.miny-1;
var AreaData = this.Area;
var ptd = new Array();
var fp = new Array();
var dx = _dx - minx;
var dy = _dy - miny;
var sx = _sx - minx;
var sy = _sy - miny;
var newg;
var cx = 0;
var cy = 0;
var node;
var stime = new Date();
var nodecenters = new Array();
var distsq = _dist * _dist;
var _done = false;
//node grid array used to hold references
var ng = new Array();
ng.length = height+1;
for(var i = 0; i<ng.length; i++){
ng[i] = new Array();
ng[i].length = width+1;
}
//starting and ending node's
var enode = new oNode(dx, dy);
// var fh = this[FORWARDHEURISTICS[_fh]](dx, dy, sx, sy)*_factor;
var fh = this.sorcheuristic(dx, dy, sx, sy, _dist);
var snode = new oNode(sx, sy, false, true, -1, 0, fh);
snode.f = snode.h;
ng[snode.y][snode.x] = snode;
oq.Insert(snode);
// calculate a general point set with the current level of detail
// var pointset = mbm_CalcPointSet(0, 0, _dist, _dstep, _rstep, 0);
var pointset = new Array();
var sets = 0;
for (var d = _dist; d > 3; d -= (_dist / _dstep)) {
pointset[sets] = new Array();
for (var r = 0; r < _rstep; r++) {
var angle = ((Math.PI*2) / _rstep) * r;
// print("angle " + r + " : " + angle + " d= " + d);
pointset[sets].push({x:(Math.cos(angle)*d),y:(Math.sin(angle)*d)});
// print("ponit " + p2s(pointset[sets][pointset[sets].length-1]));
}
sets++;
}
//pdis = new oTerminal(100, 30, 40, 40, 6, 0);
nextnode:
while (node = oq.Remove())
{
//updateterminal(AreaData, node.x, node.y);
if(Math.abs(node.x - enode.x) < _err && Math.abs(node.y - enode.y) < _err) { //Found the destination
// print("found end");
_done = true;
this.LastScore = node.f;
// if(_reduc == 99)
// return node.f;
//BUILD PATH USING REFRENCED PARENTS
var donebuild = false;
ptd.push(node);
if (ptd[ptd.length-1].parent!=-1) do {
ptd.push(ptd[ptd.length-1].parent);
if (ptd[ptd.length-1].parent==-1)
donebuild=true;
} while (!donebuild);
// Reverse the path
for (var d = ptd.length-1; d>=0; d--) {
fp.push(ptd[d]);
}
this.Path = new Array();
//Put the offset back in and move to path
for (var d = 0; d<fp.length; d++)
this.Path[d] = {x:fp[d].x + minx, y:fp[d].y + miny}
// print("Total pathing time: " + (new Date() - stime));
return this.Path;
}
else { // look for adjacent blocks that we attach to and add them to open
// Check for already visited point
// if (AreaData[node.y][node.x] & 0x100000) continue;
// Check for previous nodes... obfuscation
for (var i = 0; i < nodecenters.length; i++) {
if (nodecenters[i].id != node.parent.id) {
if (mbm_PointInCircle(nodecenters[i], distsq, node)) {
// print("in circle, skipping");
continue nextnode;
}
}
}
// if (!_isopen(AreaData, node.x, node.y)) {
// continue;
// }
// nodecenters.push(node);
// for (i = 0; i < pointset.length; i++) {
// points.push({x:pointset[i].x + node.x,y:pointset[i].y + node.y});
// }
// points = mbm_CalcPointSet(node.x, node.y, _dist, _dstep, _rstep, 0);
// print("Adding " + points.length + " points");
nextpoint:
for (var i = 0; i < pointset[0].length; i++) {
for (var dd = 0; dd < sets; dd++) {
cx = parseInt(pointset[dd][i].x + node.x);
cy = parseInt(pointset[dd][i].y + node.y);
// print("height " + height + " cy: " + cy + " pointset["+dd+"]["+i+"]: " + p2s(pointset[dd][i]) + " d: " + dd);
//check for map edge
if (cy <= 1 || cy >= height - 1 || cx <= 1 || cx >= width - 1) continue;
//check for walkability and small diagonal gaps that cant be passed
if (!DontLoadRooms) {
if (AreaData[cy][cx] == undefined) {
if (DelayLoadRooms) {
this.LoadPos(cx + this.minx, cy + this.miny);
if (AreaData[cy][cx] == undefined) continue;
} else continue;
}
if (AreaData[cy][cx] & 1) continue;
if (!_isopen(AreaData, cx, cy)) continue;
} else {
var v = this.RoomXY(cx + minx, cy + miny);
if (v & 1) continue;
if (!this.IsOpenXY(cx + minx, cy + miny)) continue;
}
// Check for previous nodes... obfuscation
// for (var xxx = 0; xxx < nodecenters.length; xxx++) {
// if (nodecenters[xxx].id == node.parent.id) {
// if (mbm_PointInCircle(nodecenters[xxx], distsq - 4, {x:cx,y:cy})) {
// // print("in circle, skipping");
// continue nextpoint;
// }
// }
// }
// if ((vx*vy) && (AreaData[cy][node.x] & 1) && (AreaData[node.y][cx] & 1)) continue;
// Find an "opener" space
// node = _findopener(AreaData, node);
// newg = node.g + points[i].dist; // SCORE[Math.abs(vx*vy)];
newg = node.g + 1;
var cnode = ng[cy][cx];
var fh = this.sorcheuristic(dx,dy,cx,cy,_dist);
// var fh = this[FORWARDHEURISTICS[_fh]](dx, dy, cx, cy)*_factor;
if(!cnode) {
cnode = new oNode(cx,cy,false,false,node,newg,fh);
// cnode = new oNode(cx,cy,false,false,node,node.g+1,this.sorcheuristic(dx,dy,cx,cy,_dist));
ng[cy][cx] = cnode;
}
else {
if (cnode.g > newg){
cnode.closed = false;
cnode.g = newg;
cnode.parent = node;
}
else continue;
}
cnode.f = cnode.g + cnode.h;
if(!cnode.open) {
cnode.open = true;
oq.Insert(cnode);
//AreaData[cnode.y][cnode.x] |= 0x200000;
}
continue nextpoint;
}
}
me.overhead(oq.getLength() + " nodes");
// me.overhead(p2s({x:node.x + minx,y:node.y+miny}));
// print(p2s({x:node.x + minx,y:node.y+miny}));
// delay(30);
node.open = false; node.closed = true;
// AreaData[node.y][node.x] |= 0x100000;
nodecenters.push(node);
}
}
print("Couldnt find a path to destination");
return false;
}
function oMap_findscore(x1, y1, x2, y2)
{
return this.findpath(x1, y1, x2, y2, 0, 99, 0, 4, 1.5);
}
function oMap_pathmove(pathtodest, walkcallflag, pointtostart, recalcmaxdist, recalcalgotype, factor)
{
if(!pathtodest) pathtodest = this.Path;
if(!pointtostart) pointtostart = 0;
if(!recalcmaxdist) recalcmaxdist = 2;
if(!recalcalgotype) recalcalgotype = mlASTAR;
if(!factor) factor = 1.2;
var failedhops = 0;
for (var i=pointtostart; i<pathtodest.length; i++)
{
mlprint("moving to " + pathtodest[i].x + ", " + pathtodest[i].y);
if(me.classid == 1 && !mlInTown(me)) var retval = mlteleportto(pathtodest[i].x, pathtodest[i].y, walkcallflag, i);
else var retval = mlwalkto(pathtodest[i].x, pathtodest[i].y, walkcallflag, i);
if (!retval)
{
if(me.area != this.AreaInitialized);
this.InitializeMap();
print("First destination failed, attempting recalculating a course to the next coordinate");
var midpath = this.FindPath(me.x, me.y, pathtodest[i].x, pathtodest[i].y, recalcmaxdist, 0, recalcalgotype, 4);
if (!midpath)
{
mlprint("mlMap:mlWalkThePath - Couldn't recalculate a path");
this.LastError = "mlMap:mlWalkThePath - Couldn't recalculate a path";
return false;
}
for(var k = 0; k<midpath.length; k++) {
if(me.classid == 1 && !mlInTown(me)) retval = mlteleportto(midpath[k].x, midpath[k].y, walkcallflag, i);
else retval = mlwalkto(midpath[k].x, midpath[k].y, walkcallflag, i);
}
}
else if (retval > mlSTEPAHEAD && retval < mlSTEPBACK) { // step ahead
i += (retval - mlSTEPAHEAD); continue; }
else if (retval > mlSTEPBACK)//step back
{
print("(retval - mlSTEPBACK):" + (retval - mlSTEPBACK));
for (var j = i; j > i - (retval - mlSTEPBACK); j--) {
if(me.classid == 1) mlteleportto(pathtodest[j].x, pathtodest[j].y, false);
else mlwalkto(pathtodest[j].x, pathtodest[j].y, false);
}
i -= (retval - mlSTEPBACK);
continue;
}
else if (retval == mlSTOP) { //step back
return mlSTOP; }
if (!retval)
{
print("We couldnt find a way to the next path point");
if(failedhops == 5)
{
mlprint("mlMap:mlWalkThePath - had five failed destinations along this path");
this.LastError = "mlMap:mlWalkThePath - had five failed destinations along this path";
return false;
}
failedhops++;
}
//delay(50);
}
return true;
}
//////////////////////////////////////////////////////////////////////
// Forward Heuristics functions - DO NOT TOUCH
// -------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
this.manhattan = function(x1, y1, x2, y2) {
return Math.abs(x2-x1) + Math.abs(y2-y1);
}
this.euclidian = function(x1, y1, x2, y2) {
return Math.floor(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
this.euclidiannosqrt = function(x1, y1, x2, y2) {
return Math.floor((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
this.nofh = function(x1, y1, x2, y2) {
return 0;
}
this.diagshortcut = function(x1, y1, x2, y2) {
var dy = Math.abs(y2-y1);
var dx = Math.abs(x2-x1);
if (dy <= dx) return dy*0.414 + dx; else return dx*0.414 + dy;
}
this.maxdxdy = function(x1, y1, x2, y2) {
var dy = Math.abs(y2-y1);
var dx = Math.abs(x2-x1);
return (dx>dy)?dx:dy;
}
this.sorcheuristic = function(x1, y1, x2, y2, teledist) {
return Math.floor(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) / teledist);
}
//////////////////////////////////////////////////////////////////////
// misc private functions
// -------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
// _isinrange
function _isinrange(_x, _y) {
if(_x > this.maxx-1 || _x < this.minx || _y > this.maxy-1 || _y < this.miny)
return false;
else
return true;
}
// updateterminal
function updateterminal(area, nx, ny) {
var mx = nx - Math.floor(pdis.Columns/2);
var my = ny - Math.floor(pdis.Rows/2);
for(var yy = 0; yy<pdis.Rows; yy++){
for(var xx = 0; xx<pdis.Columns; xx++){
if(!area[my+yy] && !area[my+yy][mx+xx]) {
pdis.Poke(yy, xx, " ");
continue;
}
if(area[my+yy][mx+xx] & 1)
pdis.Poke(yy, xx, "X");
else if(area[my+yy][mx+xx] & 0x10000)
pdis.Poke(yy, xx, "1");
else if(area[my+yy][mx+xx] & 0x20000)
pdis.Poke(yy, xx, "2");
else if(area[my+yy][mx+xx] & 0x40000)
pdis.Poke(yy, xx, "3");
else if(area[my+yy][mx+xx] & 0x80000)
pdis.Poke(yy, xx, "4");
else if(area[my+yy][mx+xx] & 0x100000)
pdis.Poke(yy, xx, "+");
else if(area[my+yy][mx+xx] & 0x200000)
pdis.Poke(yy, xx, "-");
else
pdis.Poke(yy, xx, " ");
}
}
}
function _findopener(area, node)
{
if (_isopen(area, node.x, node.y))
return node;
for (var vy = -1; vy <= 1; vy++)
for (var vx = -1; vx <= 1; vx++)
if (_isopen(area, vx, vy)) {
node.x = vx;
node.y = vy;
return node;
}
print("no opener found");
delay(100);
return node;
}
function _isopen(area, x, y) {
if (x < 1) x = 1;
if (y < 1) y = 1;
for (var vy = y-1; vy <= y+1; vy++)
for (var vx = x-1; vx <= x+1; vx++)
if (area[vy][vx] & 1 || area[vy][vx] == undefined)
return false;
return true;
}
function _isopenxy(x, y) {
if (x < 1) x = 1;
if (y < 1) y = 1;
var v;
for (var vy = y-1; vy <= y+1; vy++)
for (var vx = x-1; vx <= x+1; vx++) {
v = this.RoomXY(vx, vy);
if (v & 1 || v == undefined)
return false;
}
return true;
}
function _xy(x, y) {
// Todo: sort rooms & do binary search, woohoo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -