在RPG Maker MV中制作“武功秘籍”

80后的玩家中,应该有不少人像我一样喜欢读武侠小说吧?而喜欢读武侠小说的人中,大概很少有不知道、没玩过智冠的《金庸群侠传》这款游戏的吧?有谁还记得这款游戏里面新武功是怎么获得的吗?——废话,当然是修炼武功秘籍呀!那好,废话不多说,咱就直接上干货,看看在RPG Maker MV中怎么制作武功秘籍。

注意:本文中的插件代码适用于RPG Maker MV 1.5.x
声明:原创内容,你可以直接使用于任何商业的、非商业的游戏,也可以修改代码以适应你的需求,但是要保留原作者的版权信息。由于使用本代码而直接或间接造成的损失以及相关责任,由使用者自负,代码原作者概不负责。如果你不同意上述声明,请勿使用本文中提供的代码。

//=============================================================================
// SuTao_EquipToLearn.js
//=============================================================================
/*:
 * @plugindesc 装备特定武器、装备,在战斗中汲取一定经验后学会新技能。
 * @author sutao80216
 * 
 * @param 汲取固定经验
 * @type select
 * @option 固定(默认值)
 * @value true
 * @option 不固定
 * @value false
 * @desc 无论战斗规模,每场战斗汲取的经验值固定。
 * true - 固定(默认);false - 不固定。
 * @default true
 * 
 * @param 固定经验值
 * @type number
 * @min 0
 * @desc 每场战斗固定汲取的经验值。
 * 默认值:10
 * @default 10
 *
 * @param 经验值比例
 * @desc 汲取固定经验关闭时,汲取经验值与战斗经验的比例。它可
 * 以是浮点数或表达式,如this.level/10或0.1,this为装备者。
 * @default Math.ceil(this.mdf / 15) * 0.2
 *
 * @param 完成周目数变量ID
 * @type number
 * @min 0
 * @desc 保存已完成周目数的变量ID。
 * 不用的话设为0即可。
 * 默认值:0
 * @default 0
 *
 * @param 每周目增加可研习武功数量
 * @type number
 * @min 0
 * @desc 每完成一个周目,增加的可研习武功数量。
 * 不用的话设为0即可。
 * 默认值:0
 * @default 0
 *
 * @help 
 * Version 1.0
 * 
 * 建议配合YEP_ItemCore, YEP_EquipCore以及YEP_X_EquipRequirements来使用本插件。
 * 如果使用了上述插件,请将本插件置于它们之下。
 * 
 * ================Notetag================
 * 适用于Weapon, Armor等可以装备到身上的物品。
 * <EquipToLearn: max_exp, skill_id, force_learn>
 * 参数说明:
 *   max_exp:     习得技能所需要之经验值总量,不可省略。
 *   skill_id:    可以习得的技能之ID,不可省略。
 *   force_learn: 是否可以重新学习曾经学会但被遗忘的技能,可省略。
 *                0 - 否(默认);1 - 是。
 * 【注意】如果输入了多条上述指令,仅有最顶部的一条生效。
 */
var Imported = Imported || {};
Imported.SuTao_EquipToLearn = true;
var SuTao = SuTao || {};
SuTao.ETL = SuTao.ETL || {};
SuTao.ETL.version = 1.0;

(function ($) {
    'use strick';
    $.Paramaters = PluginManager.parameters('SuTao_EquipToLearn');
    $.Param = $.Param || {};
    $.Param.gainSolidExp = eval(String($.Paramaters['汲取固定经验'] || 'true'));
    $.Param.solidExp = Number($.Paramaters['固定经验值']) || 10;
    $.Param.expPercent = String($.Paramaters['经验值比例']);
    $.Param.circleCountId = Number($.Paramaters['完成周目数变量ID']) || 0;
    $.Param.maxCountPerCircle = Number($.Paramaters['每周目增加可研习武功数量']) || 0;

    //=============================================================================
    // DataManager
    //=============================================================================

    $.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
    DataManager.isDatabaseLoaded = function () {
        if (!$.DataManager_isDatabaseLoaded.call(this)) return false;
        if (!SuTao._loaded_EquipToLearn) {
            this.processEquipToLearnNotetags($dataWeapons);
            this.processEquipToLearnNotetags($dataArmors);
            SuTao._loaded_EquipToLearn = true;
        }
        return true;
    };

    DataManager.processEquipToLearnNotetags = function (group) {
        var regexp1 = /[ ]*<[ ]*EquipToLearn:[ ]*(\d+),[ ]*(\d+)[,]?[ ]*(\d+)?[ ]*>[ ]*/i;

        for (var n = 1; n < group.length; n++) {
            var obj = group[n];
            var notedata = obj.note.split(/[\r\n]+/);
            // 初始化修炼信息
            obj.EquipToLearn = {
                'max_exp': 0,
                'skill_id': 0,
                'force_learn': false
            };

            for (var i = 0; i < notedata.length; i++) {
                var line = notedata[i];
                if (line.match(regexp1)) {
                    obj.EquipToLearn.max_exp = parseInt(RegExp.$1);
                    obj.EquipToLearn.skill_id = parseInt(RegExp.$2);
                    obj.EquipToLearn.force_learn = parseInt(RegExp.$3) > 0;
                    // 一件装备只能修炼一个技能
                    break;
                }
            }
        }
    };

    //=============================================================================
    // Game_Actor
    //=============================================================================
    $.Game_Actor_gainExp = Game_Actor.prototype.gainExp;
    Game_Actor.prototype.gainExp = function (exp) {
        // 先调用原始方法
        $.Game_Actor_gainExp.call(this, exp);
        var equip = {};
        this._expPercent = eval($.Param.expPercent) || 0.1;
        var _exp = $.Param.gainSolidExp ? $.Param.solidExp : exp * this._expPercent;
        var _ret = {};

        for (var i = 0; i < this._equips.length; i++) {
            // 如果装备栏是空的则下一个
            if (!this._equips[i].object()) continue;
            equip = this._equips[i].object();
            // 如果不是可修炼型装备则下一个
            if (equip.EquipToLearn.max_exp <= 0 || equip.EquipToLearn.skill_id <= 0) continue;
            // 更新修炼经验,如果经验积满则学习新技能
            _ret = this.updateEquipToLearns(equip, _exp);
            // 如果可以学习新技能,并且相关技能以前没有学习过或者可以重复学习,则可以学会新技能。
            // 有些秘籍被设置成不能重复修炼,是为了兼容
            // MrTS_SimpleSkillLeveling与SRD_SkillExtender这两个插件。
            if (_ret.canLearn && (!this._equipToLearns[_ret.id].learned || equip.EquipToLearn.force_learn)) {
                if (!this.isLearnedSkill(equip.EquipToLearn.skill_id)) {
                    if (!!this._learnedCount) {
                        // this._learnedCount++;
                    } else {
                        this._learnedCount = 0;
                    }
                    // 检查通过秘籍习得的技能数量是否达到当前周目的上限
                    if ($.Param.circleCountId > 0 && $.Param.maxCountPerCircle > 0) {
                        var _circle = $gameVariables.value($.Param.circleCountId);
                        var _maxCount = 10 + $.Param.maxCountPerCircle * _circle;
                        if (this._learnedCount < _maxCount) {
                            this.learnSkill(equip.EquipToLearn.skill_id);
                            this._learnedCount++;
                        }
                    } else if (this._learnedCount < 10) {
                        this.learnSkill(equip.EquipToLearn.skill_id);
                        this._learnedCount++;
                    }

                }

                this._equipToLearns[_ret.id].learned = true;
            }
        }
    };

    // 参数item是具体类型的物品,如道具、武器、防具等,而非抽象的Game_Item
    // 参数exp是要更新(增长)的经验值
    Game_Actor.prototype.updateEquipToLearns = function (item, exp) {
        // 如果数组未声明则初始化之
        this._equipToLearns = this._equipToLearns || [];
        if (!!Imported.YEP_ItemCore) {
            // 兼容YEP_ItemCore引入的独立物品
            // 统统转换为基础物品
            item = DataManager.getBaseItem(item);
        }

        var _matchId = -1;
        var _canLearn = false;

        // 如果数组不空则会遍历之
        this._equipToLearns.every(function (obj, id) {
            // 如果已有相关记录
            if (obj.item.etypeId === item.etypeId && obj.item.id === item.id) {
                // 保存对应的序号
                _matchId = id;
                // 处理经验值
                obj.exp += exp;
                // 如果经验值已经积满
                if (obj.exp >= item.EquipToLearn.max_exp) {
                    // 可以学习新技能了
                    _canLearn = true;
                    // 避免经验值溢出
                    obj.exp = obj.item.EquipToLearn.max_exp;
                }
                // 中断遍历
                return false;
            }
            // 没有相关记录则继续遍历直至完成
            return true;
        }, this);

        // 序号没有变化,表示没找到相关记录
        if (_matchId < 0) {
            // 生成记录数据对象
            var obj = {};
            obj.item = item;
            obj.exp = Math.min(exp, item.EquipToLearn.max_exp);
            _canLearn = obj.exp >= item.EquipToLearn.max_exp;
            obj.learned = false;
            // 添加对象到数组
            _matchId = this._equipToLearns.push(obj) - 1;
        }
        // 返回装备相关记录在数组中的id,以及是否可学新技能
        return {
            'id': _matchId,
            'canLearn': _canLearn
        };
    };

    //=============================================================================
    // Window_EquipSlot
    //=============================================================================
    $.Window_EquipSlot_drawItem = Window_EquipSlot.prototype.drawItem;
    Window_EquipSlot.prototype.drawItem = function (index) {
        $.Window_EquipSlot_drawItem.call(this, index);
        if (this._actor) {
            var rect = this.itemRectForText(index);
            var _exp = 0;
            var _maxExp = 0;
            var _newText1 = '    %1\%';
            var _newText2 = '  %1\%';
            var _nameText = '';
            var _percent = 0;

            if (!!this._actor._equipToLearns) {
                var obj = {};
                var _itemEquip = {};
                for (var i = 0, len = this._actor._equipToLearns.length; i < len; i++) {
                    if (!this._actor._equipToLearns[i]) continue;
                    obj = this._actor._equipToLearns[i];
                    _itemEquip = this._actor.equips()[index];
                    if (!!Imported.YEP_ItemCore) {
                        // 兼容YEP_ItemCore引入的独立物品
                        // 统统转换为基础物品
                        _itemEquip = DataManager.getBaseItem(_itemEquip);
                    }
                    if (_itemEquip && obj.item.etypeId === _itemEquip.etypeId && obj.item.id === _itemEquip.id) {
                        _exp = obj.exp;
                        _maxExp = obj.item.EquipToLearn.max_exp;
                        _percent = _exp * 100 / _maxExp;
                        if (_percent < 10) {
                            _nameText = _newText1.format(_percent.toFixed(2));
                        } else if (_percent < 100) {
                            _nameText = _newText2.format(_percent.toFixed(2));
                        } else {
                            _nameText = '研习完毕';
                        }

                        break;
                    }
                }
            }
            this.changePaintOpacity(this.isEnabled(index));
            if (_percent >= 100) {
                this.changeTextColor(this.textColor(13));
            } else {
                this.changeTextColor(this.textColor(24));
            }
            if (!!Imported.YEP_ItemCore) {
                // 启用了YEP_ItemCore.js,使用插件附带的装备显示界面
                // 此处第二个参数的修正量适用于1024x640大小的游戏窗口
                this.drawText(_nameText, rect.x + 372, rect.y, 96, this.lineHeight(), 'right');
            } else {
                // 没有启用YEP_ItemCore.js,使用默认的装备显示界面
                // 此处第二个参数的修正量适用于默认的816x624大小的游戏窗口
                this.drawText(_nameText, rect.x + 360, rect.y, 96, this.lineHeight(), 'right');
            }
            this.changePaintOpacity(true);
            this.changeTextColor(this.systemColor());
        }
    };
})(SuTao.ETL);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容