//=============================================================================

/*:
 * @plugindesc findDirectionを斜め対応させる
 * 
 * @author LefTonbo
 *
 * @param Pass Search Limit
 * @type number
 * @desc 経路探索のリミット
 * デフォルト値: 14
 * @default 14
 *
 * @help
 * 特になし！
 */

//=============================================================================

var Imported = Imported || {};
Imported.LP_SearchDiagonalMove = true;

var LeftPlugin = LeftPlugin || {};

LeftPlugin.Parameters = PluginManager.parameters('LP_SearchDiagonalMove');
LeftPlugin.Param = LeftPlugin.Param || {};

LeftPlugin.Param.PassSearchLimit = Number(LeftPlugin.Parameters['Pass Search Limit']);

//=============================================================================

(function() {

//=============================================================================
// Game_Map
//=============================================================================

Game_Map.prototype.distance8 = function(x1, y1, x2, y2) {
    return Math.max( Math.abs(this.deltaX(x1, x2)) , Math.abs(this.deltaY(y1, y2)) );
};

Game_Map.prototype.roundXWith8Direction = function(x, d) {
    return this.roundX(x + (d === 3 || d === 6 || d === 9 ? 1 : d === 1 || d === 4 || d === 7 ? -1 : 0));
};

Game_Map.prototype.roundYWith8Direction = function(y, d) {
    return this.roundY(y + (d === 1 || d === 2 || d === 3 ? 1 : d === 7 || d === 8 || d === 9 ? -1 : 0));
};

//=============================================================================
// Game_CharacterBase
//=============================================================================

Game_CharacterBase.prototype.canPass8 = function(x, y, d) {
    var h = 0;
    var v = 0;
    if      (d === 3 || d === 6 || d === 9) h = 6;
    else if (d === 1 || d === 4 || d === 7) h = 4;
    if      (d <= 3) v = 2;
    else if (d >= 7) v = 8;
    return this.canPassDiagonally(x, y, h, v);
};

//=============================================================================
// Game_Character
//=============================================================================

// 再定義
Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
    var searchLimit = this.searchLimit();
    var mapWidth = $gameMap.width();
    var nodeList = [];
    var openList = [];
    var closedList = [];
    var start = {};
    var best = start;

    if (this.x === goalX && this.y === goalY) {
        return 0;
    }

    start.parent = null;
    start.x = this.x;
    start.y = this.y;
    start.g = 0;
    start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
    nodeList.push(start);
    openList.push(start.y * mapWidth + start.x);

    while (nodeList.length > 0) {
        var bestIndex = 0;
        for (var i = 0; i < nodeList.length; i++) {
            if (nodeList[i].f < nodeList[bestIndex].f) {
                bestIndex = i;
            }
        }

        var current = nodeList[bestIndex];
        var x1 = current.x;
        var y1 = current.y;
        var pos1 = y1 * mapWidth + x1;
        var g1 = current.g;

        nodeList.splice(bestIndex, 1);
        openList.splice(openList.indexOf(pos1), 1);
        closedList.push(pos1);

        if (current.x === goalX && current.y === goalY) {
            best = current;
            break;
        }

        if (g1 >= searchLimit) {
            continue;
        }

        for (var j = 0; j < 8; j++) {
            var direction = 2 * (j & 3) + (j >= 4 ? 1 : 2) + (j >= 6 ? 2 : 0);
            var x2 = $gameMap.roundXWith8Direction(x1, direction);
            var y2 = $gameMap.roundYWith8Direction(y1, direction);
            var pos2 = y2 * mapWidth + x2;

            if (closedList.contains(pos2)) {
                continue;
            }
            if (!this.canPass8(x1, y1, direction)) {
                console.log(direction);
                continue;
            }

            var g2 = g1 + 1;
            var index2 = openList.indexOf(pos2);

            if (index2 < 0 || g2 < nodeList[index2].g) {
                var neighbor;
                if (index2 >= 0) {
                    neighbor = nodeList[index2];
                } else {
                    neighbor = {};
                    nodeList.push(neighbor);
                    openList.push(pos2);
                }
                neighbor.parent = current;
                neighbor.x = x2;
                neighbor.y = y2;
                neighbor.g = g2;
                neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
                if (!best || neighbor.f - neighbor.g < best.f - best.g) {
                    best = neighbor;
                }
            }
        }
    }

    var node = best;
    while (node.parent && node.parent !== start) {
        node = node.parent;
    }

    var deltaX1 = $gameMap.deltaX(node.x, start.x);
    var deltaY1 = $gameMap.deltaY(node.y, start.y);
    if (deltaX1 !== 0 || deltaY1 !== 0) {
        return this.getDiagonalDirection(deltaX1, deltaY1);
    }

    var deltaX2 = - this.deltaXFrom(goalX);
    var deltaY2 = - this.deltaYFrom(goalY);
    if (deltaX2 !== 0 || deltaY2 !== 0) {
        return this.getDiagonalDirection(deltaX2, deltaY2);
    }
    
    return 0;
};

Game_Character.prototype.getDiagonalDirection = function(x, y) {
    var direction = 5;
    if (x !== 0) {
        direction += (x < 0 ? -1 : 1);
    }
    if (y !== 0) {
        direction += (y < 0 ? 3 : -3);
    }
    if (direction == 5) {
        return 0;
    }
    return direction;
};

//=============================================================================

Game_Player.prototype.searchLimit = function() {
    return LeftPlugin.Param.PassSearchLimit;
}

//=============================================================================

})();

// EOF

