/*:zh
* @target MZ
* @plugindesc 利用备注中的 meta 数据,覆盖数据库对象的原有属性
* @author SailCat
* @help WildMetaData.js
* v 1.0.0
*
* 此插件会在数据库对象(如角色、职业、敌人、物品等)加载完成后,
* 遍历其 meta 对象中的每个键值对。
* 如果该键名是对象本身已有的属性名,则用 meta 中对应的值覆盖该属性,
* 若值无法转成原属性所需求的类型,则无事发生。
* 此插件的意义在于突破编辑器对部分字段的值限制。
*
* 例如,在角色的备注中写 <initialLevel:30>,
* 插件会将 $dataActors[actorId].initialLevel 的值从原来的数字改为 30。
* 在职业的备注中写 <expParams:[0,100,0,1]>,
* 插件会将这个职业的经验值曲线改为每级需要固定100点。
*
* 注意:覆盖后可能影响游戏平衡,请谨慎使用。
*
*/
(() => {
'use strict';
// 保存原始的 DataManager.extractArrayMetadata 方法
const sailcat_mz_DataManager_extractMetaData = DataManager.extractMetadata;
/**
* 重写 DataManager.onLoad,在处理完数据库对象后应用 meta 覆盖。
*/
DataManager.extractMetadata = function(data) {
// 先调用原方法,保证对象的 meta 已经被正确提取
sailcat_mz_DataManager_extractMetaData.call(this, data);
// 对加载的对象应用 meta 覆盖
applyMetaOverrides(data);
};
/**
* 对单个对象应用 meta 覆盖。
* @param {Object} obj - 数据库对象(如角色、物品、地图等)
*/
function applyMetaOverrides(obj) {
// 如果对象没有 meta 或者 meta 为空,直接返回
if (!obj || typeof obj !== 'object' || !obj.meta) return;
const meta = obj.meta;
// 遍历 meta 的每个键
for (const key in meta) {
if (!meta.hasOwnProperty(key)) continue;
// 检查该键名是否是对象本身的属性(即已存在的属性)
if (obj.hasOwnProperty(key)) {
const originalValue = obj[key];
const metaValueStr = meta[key]; // meta 中的值永远是字符串
// 将字符串转换为与原属性相同的类型
const convertedValue = convertValue(originalValue, metaValueStr);
// 如果转换成功(不是 undefined),则覆盖原属性
if (convertedValue !== undefined) {
obj[key] = convertedValue;
}
}
}
}
/**
* 将字符串值转换为与原始值相同的类型。
* @param {*} original - 对象的原属性值
* @param {string} str - meta 中读取的字符串
* @returns {*} 转换后的值,如果无法转换则返回 undefined
*/
function convertValue(original, str) {
// 根据原始值的类型进行转换
const type = typeof original;
if (type === 'number') {
const num = Number(str);
return isNaN(num) ? undefined : num;
}
if (type === 'string') {
return String(str);
}
if (type === 'boolean') {
// 常见布尔字符串表示:true/false, 1/0, yes/no, y/n, t/f
const lower = str.toLowerCase();
if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 't' || lower === 'y') return true;
if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'f' || lower === 'n') return false;
return undefined; // 无法识别
}
if (Array.isArray(original)) {
try {
// 尝试解析为数组,例如 "[1,2,3]"
const parsed = JSON.parse(str);
if (Array.isArray(parsed)) return parsed;
} catch (e) {
// 解析失败,忽略
}
return undefined;
}
if (type === 'object' && original !== null) {
try {
// 尝试解析为对象,例如 "{"x":1}"
const parsed = JSON.parse(str);
if (typeof parsed === 'object' && parsed !== null) return parsed;
} catch (e) {
// 解析失败
}
return undefined;
}
// 对于 null、undefined 或其他无法处理的类型,直接返回 undefined 表示不覆盖
return undefined;
}
})();