//=============================================================================
// KMS_AreaEvent.js
//   Last update: 2019/01/01
//=============================================================================

/*:
 * @plugindesc
 * [v0.1.0] Expand the trigger area for events on map.
 * 
 * @author Kameo (Kamesoft)
 *
 * @help
 * ## Set trigger area
 *
 *  Add <AreaEvent:WxH> to the comment command which placed top
 *  of the event page, the trigger area is expanded to WxH tiles.
 *  Example: <AreaEvent:3x2>
 *
 */

/*:ja
 * @plugindesc
 * [v0.1.0] マップイベントが起動する範囲を拡張する機能を追加します。
 * 
 * @author かめお (Kamesoft)
 *
 * @help
 * ## イベント起動範囲の設定
 * 
 * イベントページ先頭に置いた「注釈」に <AreaEvent:WxH> と記述すると、
 * イベント位置を左上として横幅 W、縦幅 H のタイルでイベントが起動する
 * ようになります。
 *  例: <AreaEvent:3x2>
 *
 */

var KMS = KMS || {};

(function() {

'use strict';

// 定数
var Const =
{
    debug:      false,          // デバッグモード
    pluginCode: 'AreaEvent'     // プラグインコード
};

var PluginName = 'KMS_' + Const.pluginCode;

KMS.imported = KMS.imported || {};
KMS.imported[Const.pluginCode] = true;

var AreaEvent = {};

// 正規表現
AreaEvent.regex = {
    area: /<(?:エリアイベント|AreaEvent)\s*[:\s]\s*(\d+)\s*x\s*(\d+)>/i
};

// エリア定義の原点
AreaEvent.origin =
{
    topLeft:      7,
    topCenter:    8,
    topRight:     9,
    middleLeft:   4,
    middleCenter: 5,
    middleRight:  6,
    bottomLeft:   1,
    bottomCenter: 2,
    bottomRight:  3
};

// デバッグログ
var debuglog;
if (Const.debug)
{
    debuglog = function() { console.log(arguments); };
}
else
{
    debuglog = function() { };
}

// Integer の半分
function halfInt(value)
{
    return Math.floor(value / 2);
}

// 位置をエリアイベントの設定に合わせて補正
function convertPositionForAreaEvent(x, y, area)
{
    var width  = area.width  - 1;
    var height = area.height - 1;

    switch (area.origin)
    {
    case AreaEvent.origin.topLeft:
        return { x: x, y: y };
    case AreaEvent.origin.topCenter:
        return { x: x - halfInt(width), y: y };
    case AreaEvent.origin.topRight:
        return { x: x - width, y: y };
    case AreaEvent.origin.middleLeft:
        return { x: x, y: y - halfInt(height) };
    case AreaEvent.origin.middleCenter:
        return { x: x - halfInt(width), y: y - halfInt(height) };
    case AreaEvent.origin.middleRight:
        return { x: x - width, y: y - halfInt(height) };
    case AreaEvent.origin.bottomLeft:
        return { x: x, y: y - height };
    case AreaEvent.origin.bottomCenter:
        return { x: x - halfInt(width), y: y - height };
    case AreaEvent.origin.bottomRight:
        return { x: x - width, y: y - height };
    default:
        console.assert('Invalid area origin');
    }
}


//-----------------------------------------------------------------------------
// Game_Event

var _Game_Event_setupPage = Game_Event.prototype.setupPage;
Game_Event.prototype.setupPage = function()
{
    _Game_Event_setupPage.call(this);

    this.setupAreaEventAttribute();
};

/**
 * エリアイベント用属性の設定
 */
Game_Event.prototype.setupAreaEventAttribute = function()
{
    // 初期値はサイズ 1x1
    this._areaEventAttribute = { width: 1, height: 1, origin: AreaEvent.origin.topLeft };

    var isComment = function(command)
    {
        return command && (command.code === 108 || command.code === 408);
    };

    // 注釈以外に達するまで解析
    var page = this.page();
    if (!page)
    {
        return;
    }

    var commands = page.list;
    var index    = 0;
    var command  = commands[index++];
    while (isComment(command))
    {
        var comment = command.parameters[0];
        var match   = AreaEvent.regex.area.exec(comment);
        if (match)
        {
            this._areaEventAttribute.width  = Math.max(Number(match[1]), 1);
            this._areaEventAttribute.height = Math.max(Number(match[2]), 1);
            debuglog(this._areaEventAttribute);
            break;
        }

        command = commands[index++];
    }
};

/**
 * イベントのトリガー位置とサイズを取得 (他プラグイン用)
 *
 * @return {object} イベントのトリガー位置とサイズを格納したオブジェクト
 */
Game_Event.prototype.getEventTriggerArea = function()
{
    var area = this._areaEventAttribute;
    var pos  = convertPositionForAreaEvent(this._x, this._y, area);
    return { x: pos.x, y: pos.y, width: area.width, height: area.height, origin: area.origin };
};

Game_Event.prototype.pos = function(x, y)
{
    var area = this._areaEventAttribute;
    var pos  = convertPositionForAreaEvent(x, y, area);

    return pos.x >= this._x &&
        pos.x <  this._x + area.width &&
        pos.y >= this._y &&
        pos.y <  this._y + area.height;
};

})();

