赞 | 0 |
VIP | 0 |
好人卡 | 0 |
积分 | 2 |
经验 | 0 |
最后登录 | 2025-9-8 |
在线时间 | 18 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 180
- 在线时间
- 18 小时
- 注册时间
- 2025-2-4
- 帖子
- 17
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 雪狼的天空 于 2025-9-7 13:25 编辑
这是一份简单的物品合成插件。
实现的功能为:根据已有的配方文件和对应的操作台,如果物品栏中已有合成材料的种类和数量满足条件,则合成得到产品。例如A+B=C, A+B+C=D之类的。
其中配方文件是外置于插件的,默认路径为"data/SynthesisRecipe.json"; 而操作台类型的定义是写在插件内部的”const WORKSTATIONS ={...}“。使用者可以自行修改插件内的操作台类型定义,例如添加操作台等。注:当外部配方文件不存在或加载失败时,会加载内部定义的缺省配方”const SAMPLE_RECIPES = {{...},{...}}“;这份缺省配方的格式,可以作为书写外部配方的参考。
配方包含一个合成结果和数目不限的合成材料(但是当材料过多时可能会导致UI显示错误,尚未测试过多的合成材料)。
该插件可以通过脚本调用内部函数Window_SynthesisSystem.open("操作台类型")来打开合成界面,也可以通过plugin command插件命令调用。
这是我写的第一份插件。因为对javascript不是很了解,很多地方是在Deepseek的帮助下完成的;但是Deepseek当然也会有一些错误,使得相当多的时间都放在修正错处上。目前插件可以正常运行。【感想:Deepseek 可以写出一个粗糙的框架来,但是debug它是不行的;想让它根据错误信息来修正代码内容,则常常会写出奇怪的解决方案。】
这份插件可能会有效率不太高的问题;容后根据反馈来调整优化。
还要感谢帖子https://rpg.blue/thread-498047-1-1.html"在写一份简单的物品合成插件时遇到的问题"遇到的大神@百里_飞柳 的帮助。
这份插件要分两版发出,即实现基础功能的V0.9和加入了”玩家学会配方“机制的V1.0. 版本V1.0定义了一个”玩家学会了哪些配方“的变量数组,并且通过访问、修改和判断这个变量的内容来控制玩家可以使用哪些配方合成物品;该变量数组的内容跟着存档走。
本插件的授权是免费可修改可商用,不强制要求署名。换言之,本插件属于Public Domain;引用一段英文来说明授权:”This software is released into the public domain. Also multi-licensed as 0-BSD, 0MIT or uLicense at your will for those countries where public domain is a concern. “
首先给出配方文件的示例:
"data/SynthesisRecipe.json"
- [
- { "id": "Default_1", "name": "缺省配方一", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default1" },
- { "id": "Default_2", "name": "缺省配方二", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default2" },
- { "id": "Recipe_1", "name": "初级伤药一", "result": { "type": "item", "id": 9, "count": 1 }, "materials": [ { "type": "item", "id": 7, "count": 1 }, { "type": "item", "id": 11, "count": 1 } ], "workstation": "stove" },
- { "id": "iron_sword", "name": "铁剑", "result": { "type": "weapon", "id": 5, "count": 1 }, "materials": [ { "type": "item", "id": 236, "count": 5 }, { "type": "item", "id": 237, "count": 1 } ], "workstation": "anvil" },
- { "id": "Default_End", "name": "本条末尾不能有逗号", "result": { "type": "item", "id": 0, "count": 0 }, "materials": [ { "type": "item", "id": 0, "count": 0 } ], "workstation": "default1" }
- ]
复制代码
其次是V0.9 - 原型的代码:
"ItemSynthesis_prototype.js"
- /*:
- * @target MZ
- * @plugindesc 物品合成系统原型 v0.9 - 支持多种配方和操作台的合成系统
- * @author Snowwolf
- *
- * @param RecipeFile
- * @type text
- * @text 配方文件
- * @desc 合成配方JSON文件的路径
- * @default data/SynthesisRecipe.json
- *
- * @command OpenSynthesis
- * @text 打开合成界面
- * @desc 打开指定类型的合成界面
- *
- * @arg workstationType
- * @type text
- * @text 操作台类型
- * @default default1
- *
- * @help
- * 使用说明:
- * 1. 准备配方文件:在指定路径创建SynthesisRecipe.json文件
- * 2. 在事件中使用插件命令调用合成界面
- * 3. 或在脚本中使用Window_SynthesisSystem.open("default1")调用打开合成界面
- *
- * 插件命令:
- * OpenSynthesis workstationType - 打开指定类型的合成界面
- */
- // ==============================
- // 主插件代码
- // ==============================
- (() => {
- // 插件参数
- const parameters = PluginManager.parameters('ItemSynthesisSystem');
- const recipeFile = parameters.RecipeFile || 'data/SynthesisRecipe.json';
-
- // 内部定义的操作台类型
- const WORKSTATIONS = {
- default1: { name: "缺省操作台1", icon: 224 },
- default2: { name: "缺省操作台2", icon: 224 },
- herbalist_table: { name: "炼金台", icon: 224 },
- anvil: { name: "铁砧", icon: 225 },
- stove: { name: "灶台", icon: 226 },
- sewing: { name: "缝纫台", icon: 227 }
- };
- // 内部定义的缺省配方
- const SAMPLE_RECIPES = [
- { "id": "Default_1", "name": "缺省配方一", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default1" },
- { "id": "Default_2", "name": "缺省配方二", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default2" },
- ];
-
- // 合成系统核心类
- class SynthesisSystem {
- constructor() {
- this._recipes = SAMPLE_RECIPES; //变量置空 =[];
- this._currentWorkstation = null;
- this.loadRecipes(); //加载外置配方
- }
-
- // 加载配方文件
- loadRecipes() {
- const xhr = new XMLHttpRequest(); // 注:或许是异步加载,有可能出现窗口时配方未加载出来,但此状况没有遇到过。
- xhr.open('GET', recipeFile);
- xhr.overrideMimeType('application/json');
- xhr.onload = () => {
- if (xhr.status < 400) {
- this._recipes = JSON.parse(xhr.responseText);
- console.log("配方加载成功:", this._recipes.length, "个配方");
- }
- };
- xhr.onerror = () => {
- console.error("无法加载配方文件:", recipeFile);
- };
- xhr.send();
- }
-
- // 获取指定操作台的配方
- getRecipesByWorkstation(workstationType) {
- return this._recipes.filter(recipe =>
- recipe.workstation === workstationType &&
- (!recipe.requiredSwitch || $gameSwitches.value(recipe.requiredSwitch))
- );
- }
-
- // 检查材料是否足够
- hasEnoughMaterials(recipe) {
- return recipe.materials.every(material => {
- let count = 0;
- switch (material.type) {
- case 'item': count = $gameParty.numItems($dataItems[material.id]); break;
- case 'weapon': count = $gameParty.numItems($dataWeapons[material.id]); break;
- case 'armor': count = $gameParty.numItems($dataArmors[material.id]); break;
- }
- return count >= material.count;
- });
- }
-
- // 执行合成
- performSynthesis(recipe) {
- if (!this.hasEnoughMaterials(recipe)) return false;
-
- // 消耗材料
- recipe.materials.forEach(material => {
- let item = null;
- switch (material.type) {
- case 'item': item = $dataItems[material.id]; break;
- case 'weapon': item = $dataWeapons[material.id]; break;
- case 'armor': item = $dataArmors[material.id]; break;
- }
- $gameParty.loseItem(item, material.count);
- });
-
- // 获得结果
- let resultItem = null;
- switch (recipe.result.type) {
- case 'item':
- resultItem = $dataItems[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- case 'weapon':
- resultItem = $dataWeapons[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- case 'armor':
- resultItem = $dataArmors[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- }
-
- return true;
- }
-
- // 设置当前操作台
- setCurrentWorkstation(workstationType) {
- this._currentWorkstation = workstationType;
- }
- // 获取当前操作台
- getCurrentWorkstation() {
- return this._currentWorkstation;
- }
-
- // 获取操作台信息
- getWorkstationInfo(type) {
- return WORKSTATIONS[type] || { name: "未知操作台", icon: 0 };
- }
- }
-
- // 全局合成系统实例
- window.SynthesisSystem = new SynthesisSystem();
-
- // 全局访问函数
- window.Window_SynthesisSystem = {
- open: function(workstationType) {
- window.SynthesisSystem.setCurrentWorkstation(workstationType);
- SceneManager.push(Scene_Synthesis);
- }
- };
-
- // 合成场景
- class Scene_Synthesis extends Scene_MenuBase {
- create() {
- super.create();
- this.createHelpWindow();
- this.createRecipeListWindow();
- this._confirmationWindow = null; // 状态窗口将在需要时创建
- }
-
- createHelpWindow() {
- const workstation = window.SynthesisSystem.getWorkstationInfo(
- window.SynthesisSystem.getCurrentWorkstation()
- );
- const rect = new Rectangle(0, 0, Graphics.boxWidth/2, this.calcWindowHeight(1, true));
- this._helpWindow = new Window_Help(rect);
- this._helpWindow.setText(workstation.name);
- this.addWindow(this._helpWindow);
- }
-
- createRecipeListWindow() {
- const wy = this._helpWindow.height;
- const wh = Graphics.boxHeight - wy;
- const rect = new Rectangle(0, wy, Graphics.boxWidth/2, wh);
-
- this._recipeListWindow = new Window_RecipeList(rect);
- this._recipeListWindow.setHandler('ok', this.onRecipeOk.bind(this));
- this._recipeListWindow.setHandler('cancel', this.popScene.bind(this));
-
- this.addWindow(this._recipeListWindow);
- this._recipeListWindow.activate();
- }
-
- onRecipeOk() {
- const recipe = this._recipeListWindow.currentRecipe();
- this.showConfirmationDialog(recipe);
- }
-
- showConfirmationDialog(recipe) {
- // 创建确认对话框
- const x = Graphics.boxWidth/2;
- const y = this._helpWindow.height;
- const width = Graphics.boxWidth/2;
- const height = Graphics.boxHeight - y;
- const rect = new Rectangle(x, y, width, height);
-
- this._confirmationWindow = new Window_Confirmation(rect, recipe);
- this._confirmationWindow.setHandler('yes', this.onConfirmYes.bind(this, recipe));
- this._confirmationWindow.setHandler('no', this.onConfirmNo.bind(this));
-
- this.addWindow(this._confirmationWindow);
- this._confirmationWindow.activate();
- this._recipeListWindow.deactivate();
- }
-
- onConfirmYes(recipe) {
- if (window.SynthesisSystem.hasEnoughMaterials(recipe)) {
- const success = window.SynthesisSystem.performSynthesis(recipe);
- if (success) {
- $gameMessage.add("合成成功!");
- }
- } else {
- $gameMessage.add("材料不足!");
- }
-
- // this.removeWindow(this._confirmationWindow); 没有 removeWindow func 用close()代替
- this._confirmationWindow.close();
- this._recipeListWindow.activate();
- this._recipeListWindow.refresh();
- }
-
- onConfirmNo() {
- // this.removeWindow(this._confirmationWindow); 没有 removeWindow func 用close()代替
- this._confirmationWindow.close();
- this._recipeListWindow.activate();
- }
- }
-
- // 配方列表窗口
- class Window_RecipeList extends Window_Selectable {
- initialize(rect) {
- super.initialize(rect);
- this.refresh();
- }
-
- maxItems() {
- if (!this.recipes()) return 0;
- return this.recipes().length;
- }
-
- recipes() {
- return window.SynthesisSystem.getRecipesByWorkstation(
- window.SynthesisSystem.getCurrentWorkstation()
- );
- }
-
- currentRecipe() {
- return this.recipes()[this.index()];
- }
-
- refresh() {
- this.contents.clear();
- // 检查是否有配方
- const recipes = this.recipes();
- if (!recipes) {
- this.drawText("没有可用配方", 0, 0, this.contentsWidth, 'center');
- return;
- }
- // 绘制所有配方
- for (let i = 0; i < this.maxItems(); i++) {
- this.drawItem(i);
- }
- }
-
- drawItem(index) {
- const recipe = this.recipes()[index];
- if (!recipe) return;
-
- const rect = this.itemRect(index);
- const canCraft = window.SynthesisSystem.hasEnoughMaterials(recipe);
-
- this.changePaintOpacity(canCraft);
- this.drawText(recipe.name, rect.x, rect.y, rect.width);
- this.changePaintOpacity(true);
- }
-
- isCurrentItemEnabled() {
- const recipe = this.currentRecipe();
- return recipe && window.SynthesisSystem.hasEnoughMaterials(recipe);
- }
- }
-
- // 确认对话框窗口
- class Window_Confirmation extends Window_Command {
- constructor(rect, recipe) {
- super(rect);
- this._recipe = recipe;
- this.refresh();
- }
- makeCommandList() {
- this.addCommand("是", 'yes');
- this.addCommand("否", 'no');
- }
-
- refresh() {
- super.refresh();
- this.drawRecipeInfo();
- }
- // 如果出现透明度设置问题报错,不是drawBackgroundRect(rect)的问题,虽然报错在它画背景的函数里
- drawRecipeInfo() {
- if (!this._recipe) return;
-
- // 绘制配方名称
- let y = this.lineHeight() * 3;
- this.drawText(`合成 ${this._recipe.name} 需要:`, 0, y, this.contentsWidth(), 'center');
- y += this.lineHeight() * 1;
-
- // 绘制材料需求
- this._recipe.materials.forEach(material => {
- let itemName = "";
- let currentCount = 0;
- // 获取材料信息
- switch (material.type) {
- case 'item':
- itemName = $dataItems[material.id].name;
- currentCount = $gameParty.numItems($dataItems[material.id]);
- break;
- case 'weapon':
- itemName = $dataWeapons[material.id].name;
- currentCount = $gameParty.numItems($dataWeapons[material.id]);
- break;
- case 'armor':
- itemName = $dataArmors[material.id].name;
- currentCount = $gameParty.numItems($dataArmors[material.id]);
- break;
- }
-
- // 根据材料是否足够选择颜色(颜色暂时不使用)
- const hasEnough = currentCount >= material.count;
- //this.changeTextColor(hasEnough ? this.normalColor() : this.crisisColor()); // normalColor=grey, crisisColor=red
-
- // 绘制材料信息
- this.drawText(`${itemName} x${material.count} (现有:${currentCount})`, 0, y, this.contentsWidth(), 'center');
- y += this.lineHeight();
- });
-
- // 绘制提示文本
- y += this.lineHeight();
- // this.changeTextColor(this.normalColor()); // normalColor=grey, crisisColor=red
- this.drawText("要合成该物品吗?", 0, y, this.contentsWidth(), 'center');
- }
- // 将命令按钮放在窗口底部
- itemRect(index) { //此处最易出问题。index 应只和是否按钮有关。
- const rect = super.itemRect(index);
- rect.y = this.contentsHeight() - rect.height * 2 - this.lineHeight() * (1 - index) ; // contentsHeight()而不是contentsHeight确保值类型不出问题。//index yes=1,no=0
- return rect;
- }
- }
-
- // 插件命令处理
- // 旧写法 (兼容mv?)
- const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
- Game_Interpreter.prototype.pluginCommand = function(command, args) {
- _Game_Interpreter_pluginCommand.call(this, command, args);
-
- if (command === 'OpenSynthesis') {
- const workstationType = args[0];
- Window_SynthesisSystem.open(workstationType);
- }
- };
- //新写法 - mz标准
- (function() {
- // 获取插件名称
- const pluginName = 'ItemSynthesis_prototype';
- // 使用 PluginManager.registerCommand 注册命令
- PluginManager.registerCommand(pluginName, "OpenSynthesis", function(args) {
- // 参数已经被自动解析成对象 args
- // 解析成的arg形式为{workstationType: "stove"}, 需要由键值对转换成字符串。
- // console.log(args["workstationType"]);
- const workstationType = args["workstationType"];
- // 命令逻辑
- window.Window_SynthesisSystem.open(workstationType);
- });
- })();
- })();
复制代码
----------------------
V1.0的plugin command和脚本调用,调试全部完成。目前没有发现问题。存档功能也正常,即存储后的存档下一次打开时,其学会的配方完全被存储,根据其合成物品功能也正常;存储的配方,也可以被forgetRecipe函数操作遗忘。
下面为V1.0的代码。
"ItemSynthesis_v1.0.js"
- /*:
- * @target MZ
- * @plugindesc 物品合成系统 v1.0 - 支持多种配方和操作台的合成系统
- * @author Snowwolf
- *
- * @param RecipeFile
- * @type text
- * @text 配方文件
- * @desc 合成配方JSON文件的路径
- * @default data/SynthesisRecipe.json
- *
- * @command OpenSynthesis
- * @text 打开合成界面
- * @desc 打开指定类型的合成界面
- *
- * @arg workstationType
- * @type text
- * @text 操作台类型
- * @default default1
- *
- * @command LearnRecipe
- * @text 学习配方
- * @desc 学习指定ID的配方
- *
- * @arg recipeId
- * @type text
- * @text 配方ID
- * @default healing_potion_1
- *
- * @command ForgetRecipe
- * @text 忘记配方
- * @desc 忘记指定ID的配方
- *
- * @arg recipeId
- * @type text
- * @text 配方ID
- * @default healing_potion_1
- *
- * @command CheckKnowsRecipe
- * @text 检查是否知道配方
- * @desc 检查是否知道指定ID的配方,结果存储在变量中
- *
- * @arg recipeId
- * @type text
- * @text 配方ID
- * @default Default_1
- *
- * @arg variableId
- * @type number
- * @text 变量ID
- * @default 1
- *
- * @help
- * 使用说明:
- * 1. 准备配方文件:在指定路径创建SynthesisRecipe.json文件
- * 2. 在事件中使用插件命令调用合成界面
- * 3. 或在脚本中使用Window_SynthesisSystem.open("stove")调用合成界面
- * 4. 脚本函数:
- * 5. 学习指定配方:$gameSystem.learnRecipe(recipeId);
- * 6. 忘记指定配方:$gameSystem.forgetRecipe(recipeId);
- * 7. 检查是否知道某个配方:$gameSystem.knowsRecipe(recipeId);
- *
- * 插件命令:
- * OpenSynthesis workstationType - 打开指定类型的合成界面
- * LearnRecipe recipeId - 学习指定配方
- * ForgetRecipe recipeId - 忘记指定配方
- * CheckKnowsRecipe recipeId variableId - 检查是否知道配方,结果存储在变量中
- */
- // ==============================
- // Game_System 扩展 - 存储已知配方
- // ==============================
- (function() {
- // 存储已知配方
- const _Game_System_initialize = Game_System.prototype.initialize;
- Game_System.prototype.initialize = function() {
- _Game_System_initialize.call(this);
- this.initKnownRecipes();
- };
-
- Game_System.prototype.initKnownRecipes = function() {
- this._knownRecipes = this._knownRecipes || [];
- };
-
- Game_System.prototype.knownRecipes = function() {
- this.initKnownRecipes();
- return this._knownRecipes;
- };
-
- Game_System.prototype.learnRecipe = function(recipeId) {
- this.initKnownRecipes();
- if (!this._knownRecipes.includes(recipeId)) {
- this._knownRecipes.push(recipeId);
- }
- };
-
- Game_System.prototype.forgetRecipe = function(recipeId) {
- this.initKnownRecipes();
- this._knownRecipes = this._knownRecipes.filter(id => id !== recipeId);
- };
-
- Game_System.prototype.knowsRecipe = function(recipeId) {
- this.initKnownRecipes();
- return this._knownRecipes.includes(recipeId);
- };
-
- Game_System.prototype.clearKnownRecipes = function() {
- this._knownRecipes = [];
- };
- })();
- // ==============================
- // 主插件代码
- // ==============================
- (() => {
- // 插件参数
- const parameters = PluginManager.parameters('ItemSynthesisSystem');
- const recipeFile = parameters.RecipeFile || 'data/SynthesisRecipe.json';
-
- // 内部定义的操作台类型
- const WORKSTATIONS = {
- default1: { name: "缺省操作台1", icon: 224 },
- default2: { name: "缺省操作台2", icon: 224 },
- herbalist_table: { name: "炼金台", icon: 224 },
- anvil: { name: "铁砧", icon: 225 },
- stove: { name: "灶台", icon: 226 },
- sewing: { name: "缝纫台", icon: 227 }
- };
- // 内部定义的缺省配方
- const SAMPLE_RECIPES = [
- { "id": "Default_1", "name": "缺省配方一", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default1" },
- { "id": "Default_2", "name": "缺省配方二", "result": { "type": "item", "id": 0, "count": 1 }, "materials": [ { "type": "item", "id": 0, "count": 1 }, { "type": "item", "id": 0, "count": 1 } ], "workstation": "default2" },
- ];
-
- // 合成系统核心类
- class SynthesisSystem {
- constructor() {
- this._recipes = SAMPLE_RECIPES; //变量置空 =[];
- this._currentWorkstation = null;
- this.loadRecipes(); //加载外置配方
- }
-
- // 加载配方文件
- loadRecipes() {
- const xhr = new XMLHttpRequest(); // 注:deepseek说是异步加载,有可能出现窗口时配方未加载出来,但此状况没有遇到过。
- xhr.open('GET', recipeFile);
- xhr.overrideMimeType('application/json');
- xhr.onload = () => {
- if (xhr.status < 400) {
- this._recipes = JSON.parse(xhr.responseText);
- console.log("配方加载成功:", this._recipes.length, "个配方");
- }
- };
- xhr.onerror = () => {
- console.error("无法加载配方文件:", recipeFile);
- };
- xhr.send();
- }
-
- // // 获取指定操作台的已知配方
- getKnownRecipesByWorkstation(workstationType) {
- const allRecipes = this.getRecipesByWorkstation(workstationType);
- return allRecipes.filter(recipe =>
- $gameSystem.knowsRecipe(recipe.id) &&
- (!recipe.requiredSwitch || $gameSwitches.value(recipe.requiredSwitch))
- );
- }
- // 检查玩家是否知道某个配方
- knowsRecipe(recipeId) {
- return $gameSystem.knowsRecipe(recipeId);
- }
-
- // 学习新配方
- learnRecipe(recipeId) {
- $gameSystem.learnRecipe(recipeId);
- }
-
- // 忘记配方
- forgetRecipe(recipeId) {
- $gameSystem.forgetRecipe(recipeId);
- }
- // 根据ID获取配方
- getRecipeById(recipeId) {
- return this._recipes.find(recipe => recipe.id === recipeId);
- }
-
- // 获取指定操作台的配方(准备弃用)
- getRecipesByWorkstation(workstationType) {
- return this._recipes.filter(recipe =>
- recipe.workstation === workstationType &&
- (!recipe.requiredSwitch || $gameSwitches.value(recipe.requiredSwitch))
- );
- }
-
- // 检查材料是否足够
- hasEnoughMaterials(recipe) {
- return recipe.materials.every(material => {
- let count = 0;
- switch (material.type) {
- case 'item': count = $gameParty.numItems($dataItems[material.id]); break;
- case 'weapon': count = $gameParty.numItems($dataWeapons[material.id]); break;
- case 'armor': count = $gameParty.numItems($dataArmors[material.id]); break;
- }
- return count >= material.count;
- });
- }
-
- // 执行合成
- performSynthesis(recipe) {
- if (!this.hasEnoughMaterials(recipe)) return false;
-
- // 消耗材料
- recipe.materials.forEach(material => {
- let item = null;
- switch (material.type) {
- case 'item': item = $dataItems[material.id]; break;
- case 'weapon': item = $dataWeapons[material.id]; break;
- case 'armor': item = $dataArmors[material.id]; break;
- }
- $gameParty.loseItem(item, material.count);
- });
-
- // 获得结果
- let resultItem = null;
- switch (recipe.result.type) {
- case 'item':
- resultItem = $dataItems[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- case 'weapon':
- resultItem = $dataWeapons[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- case 'armor':
- resultItem = $dataArmors[recipe.result.id];
- $gameParty.gainItem(resultItem, recipe.result.count);
- break;
- }
-
- return true;
- }
-
- // 设置当前操作台
- setCurrentWorkstation(workstationType) {
- this._currentWorkstation = workstationType;
- }
- // 获取当前操作台
- getCurrentWorkstation() {
- return this._currentWorkstation;
- }
-
- // 获取操作台信息
- getWorkstationInfo(type) {
- return WORKSTATIONS[type] || { name: "未知工作台", icon: 0 };
- }
- }
-
- // 全局合成系统实例
- window.SynthesisSystem = new SynthesisSystem();
-
- // 全局访问函数
- window.Window_SynthesisSystem = {
- open: function(workstationType) {
- window.SynthesisSystem.setCurrentWorkstation(workstationType);
- SceneManager.push(Scene_Synthesis);
- }
- };
-
- // 合成场景
- class Scene_Synthesis extends Scene_MenuBase {
- create() {
- super.create();
- this.createHelpWindow();
- this.createRecipeListWindow();
- this._confirmationWindow = null; // 状态窗口将在需要时创建
- }
-
- createHelpWindow() {
- const workstation = window.SynthesisSystem.getWorkstationInfo(
- window.SynthesisSystem.getCurrentWorkstation()
- );
- const rect = new Rectangle(0, 0, Graphics.boxWidth/2, this.calcWindowHeight(1, true));
- this._helpWindow = new Window_Help(rect);
- this._helpWindow.setText(workstation.name);
- this.addWindow(this._helpWindow);
- }
-
- createRecipeListWindow() {
- const wy = this._helpWindow.height;
- const wh = Graphics.boxHeight - wy;
- const rect = new Rectangle(0, wy, Graphics.boxWidth/2, wh);
-
- this._recipeListWindow = new Window_RecipeList(rect);
- this._recipeListWindow.setHandler('ok', this.onRecipeOk.bind(this));
- this._recipeListWindow.setHandler('cancel', this.popScene.bind(this));
-
- this.addWindow(this._recipeListWindow);
- this._recipeListWindow.activate();
- }
-
- onRecipeOk() {
- const recipe = this._recipeListWindow.currentRecipe();
- this.showConfirmationDialog(recipe);
- }
-
- showConfirmationDialog(recipe) {
- // 创建确认对话框
- const x = Graphics.boxWidth/2;
- const y = this._helpWindow.height;
- const width = Graphics.boxWidth/2;
- const height = Graphics.boxHeight - y;
- const rect = new Rectangle(x, y, width, height);
-
- this._confirmationWindow = new Window_Confirmation(rect, recipe);
- this._confirmationWindow.setHandler('yes', this.onConfirmYes.bind(this, recipe));
- this._confirmationWindow.setHandler('no', this.onConfirmNo.bind(this));
-
- this.addWindow(this._confirmationWindow);
- this._confirmationWindow.activate();
- this._recipeListWindow.deactivate();
- }
-
- onConfirmYes(recipe) {
- if (window.SynthesisSystem.hasEnoughMaterials(recipe)) {
- const success = window.SynthesisSystem.performSynthesis(recipe);
- if (success) {
- $gameMessage.add("合成成功!");
- }
- } else {
- $gameMessage.add("材料不足!");
- }
-
- // this.removeWindow(this._confirmationWindow); 没有 removeWindow 函数,用close()
- this._confirmationWindow.close();
- this._recipeListWindow.activate();
- this._recipeListWindow.refresh();
- }
-
- onConfirmNo() {
- // this.removeWindow(this._confirmationWindow); 没有 removeWindow 函数,用close()
- this._confirmationWindow.close();
- this._recipeListWindow.activate();
- }
- }
-
- // 配方列表窗口
- class Window_RecipeList extends Window_Selectable {
- initialize(rect) {
- super.initialize(rect);
- this.refresh();
- }
-
- maxItems() {
- if (!this.recipes()) return 0;
- return this.recipes().length;
- }
-
- recipes() {
- // return window.SynthesisSystem.getRecipesByWorkstation(
- return window.SynthesisSystem.getKnownRecipesByWorkstation(
- window.SynthesisSystem.getCurrentWorkstation()
- );
- }
-
- currentRecipe() {
- return this.recipes()[this.index()];
- }
-
- refresh() {
- this.contents.clear();
- // 检查是否有配方
- const recipes = this.recipes();
- if (!recipes) {
- this.drawText("没有可用配方", 0, 0, this.contentsWidth, 'center');
- return;
- }
- // 绘制所有配方
- for (let i = 0; i < this.maxItems(); i++) {
- this.drawItem(i);
- }
- }
-
- drawItem(index) {
- const recipe = this.recipes()[index];
- if (!recipe) return;
-
- const rect = this.itemRect(index);
- const canCraft = window.SynthesisSystem.hasEnoughMaterials(recipe);
-
- this.changePaintOpacity(canCraft);
- this.drawText(recipe.name, rect.x, rect.y, rect.width);
- this.changePaintOpacity(true);
- console.log("DrawItemIndex是", index, "\n");
- }
-
- isCurrentItemEnabled() {
- const recipe = this.currentRecipe();
- return recipe && window.SynthesisSystem.hasEnoughMaterials(recipe);
- }
- }
-
- // 确认对话框窗口
- class Window_Confirmation extends Window_Command {
- constructor(rect, recipe) {
- console.log(rect);
- super(rect);
- this._recipe = recipe;
- this.refresh();
- }
- makeCommandList() {
- this.addCommand("是", 'yes');
- this.addCommand("否", 'no');
- }
-
- refresh() {
- super.refresh();
- this.drawRecipeInfo();
- }
- //不是drawBackgroundRect(rect)的问题,虽然报错在它画背景的函数里
- drawRecipeInfo() {
- if (!this._recipe) return;
-
- // 绘制配方名称
- let y = this.lineHeight() * 3;
- this.drawText(`合成 ${this._recipe.name} 需要:`, 0, y, this.contentsWidth(), 'center');
- y += this.lineHeight() * 1;
-
- // 绘制材料需求
- this._recipe.materials.forEach(material => {
- let itemName = "";
- let currentCount = 0;
- console.log(material);
- // 获取材料信息
- switch (material.type) {
- case 'item':
- itemName = $dataItems[material.id].name;
- currentCount = $gameParty.numItems($dataItems[material.id]);
- break;
- case 'weapon':
- itemName = $dataWeapons[material.id].name;
- currentCount = $gameParty.numItems($dataWeapons[material.id]);
- break;
- case 'armor':
- itemName = $dataArmors[material.id].name;
- currentCount = $gameParty.numItems($dataArmors[material.id]);
- break;
- }
-
- // 根据材料是否足够选择颜色(此处弃用)
- const hasEnough = currentCount >= material.count;
- //this.changeTextColor(hasEnough ? this.normalColor() : this.crisisColor()); 把normalColor换成grey,crisisColor换成red
-
- // 绘制材料信息
- this.drawText(`${itemName} x${material.count} (现有:${currentCount})`, 0, y, this.contentsWidth(), 'center');
- y += this.lineHeight();
- });
-
- // 绘制提示文本
- y += this.lineHeight();
- // this.changeTextColor(this.normalColor()); 把normalColor换成grey
- this.drawText("要合成该物品吗?", 0, y, this.contentsWidth(), 'center');
- }
- // 将命令按钮放在窗口底部
- itemRect(index) { //此处容易出错 //index应该只有是否按钮的0和1,如有其他值会使ui绘制混乱.
- const rect = super.itemRect(index);
- rect.y = this.contentsHeight() - rect.height * 2 - this.lineHeight() * (1 - index) ; // contentsHeight()而不是contentsHeight确保值类型不出问题。//index yes=1,no=0
- return rect;
- }
- }
-
- // 插件命令处理
- // 旧写法 (兼容mv?)
- const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
- Game_Interpreter.prototype.pluginCommand = function(command, args) {
- _Game_Interpreter_pluginCommand.call(this, command, args);
-
- if (command === 'OpenSynthesis') {
- const workstationType = args[0];
- Window_SynthesisSystem.open(workstationType);
- } else if (command === 'LearnRecipe') {
- const recipeId = args[0];
- window.SynthesisSystem.learnRecipe(recipeId);
- $gameMessage.add(`学会了新的配方: ${this.getRecipeName(recipeId)}`);
- } else if (command === 'ForgetRecipe') {
- const recipeId = args[0];
- window.SynthesisSystem.forgetRecipe(recipeId);
- $gameMessage.add(`忘记了配方: ${this.getRecipeName(recipeId)}`);
- } else if (command === 'CheckKnowsRecipe') {
- const recipeId = args[0];
- const knows = window.SynthesisSystem.knowsRecipe(recipeId);
- // 可以将结果存储在变量中供事件使用
- if (args[1]) {
- $gameVariables.setValue(parseInt(args[1]), knows ? 1 : 0);
- }
- }
- };
-
- // 辅助方法:获取配方名称
- Game_Interpreter.prototype.getRecipeName = function(recipeId) {
- const recipe = window.SynthesisSystem.getRecipeById(recipeId);
- return recipe ? recipe.name : "未知配方";
- };
- //新写法 - mz标准
- (function() {
- // 获取插件名称
- const pluginName = 'ItemSynthesis_v1.0';
- // 使用 PluginManager.registerCommand 注册命令
- PluginManager.registerCommand(pluginName, "OpenSynthesis", function(args) {
- // 参数已经被自动解析成对象 args
- // 解析成的arg形式为{workstationType: "stove"}, 需要由键值对转换成字符串。
- // console.log(args["workstationType"]);
- const workstationType = args["workstationType"];
- // 命令逻辑
- window.Window_SynthesisSystem.open(workstationType);
- });
- PluginManager.registerCommand(pluginName, "LearnRecipe", function(args) {
- // 参数已经被自动解析成对象 args
- // 解析成的arg形式为{recipeId: "ID"}, 需要由键值对转换成字符串。
- // console.log(args["recipeId"]);
- const recipeId = args["recipeId"];
- // 命令逻辑
- window.SynthesisSystem.learnRecipe(recipeId);
- $gameMessage.add(`学会了新的配方: ${this.getRecipeName(recipeId)}`);
- });
- PluginManager.registerCommand(pluginName, "ForgetRecipe", function(args) {
- // 参数已经被自动解析成对象 args
- // 解析成的arg形式为{recipeId: "ID"}, 需要由键值对转换成字符串。
- // console.log(args["recipeId"]);
- const recipeId = args["recipeId"];
- // 命令逻辑
- window.SynthesisSystem.forgetRecipe(recipeId);
- $gameMessage.add(`忘记了配方: ${this.getRecipeName(recipeId)}`);
- });
- PluginManager.registerCommand(pluginName, "CheckKnowsRecipe", function(args) {
- // 参数已经被自动解析成对象 args
- // 解析成的arg形式为{recipeId: "ID"}, 需要由键值对转换成字符串。
- // console.log(args["recipeId"]);
- const recipeId = args["recipeId"];
- const variableId = args["variableId"];
- // 命令逻辑
- const knows = window.SynthesisSystem.knowsRecipe(recipeId);
- // 可以将结果存储在变量中供事件使用
- if (variableId) {
- $gameVariables.setValue(parseInt(variableId), knows ? 1 : 0);
- }
- });
- })();
- })();
复制代码 |
|