赞 | 0 |
VIP | 0 |
好人卡 | 0 |
积分 | 2 |
经验 | 0 |
最后登录 | 2025-9-6 |
在线时间 | 18 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 165
- 在线时间
- 18 小时
- 注册时间
- 2025-2-4
- 帖子
- 16
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 雪狼的天空 于 2025-9-6 09:02 编辑
如题所示。
我要写的这个插件,它本身有着从外界读取合成配方的功能,并且使用内部定义区分了不同操作台。例如灶台只能做饭,铁砧只能打造武器等等。
它分为主管配方控制和物品合成核心功能的核心类SynthesisSystem,用于打开合成场景的Scene_Synthesis,用于显示配方列表的窗口类Window_RecipeList,用于确认合成的对话框类Window_Confirmation。
我的问题是:对于显示配方列表的窗口类Window_RecipeList,它是Window_Command类的扩展,所以在Window_RecipeList的构造函数中,需要先用super引用父类的构造函数Window_Command(rectangle),但是,我无论super传入一个什么样的rectangle,就算是new Rectangle(0,0,1,1),都会显示报错“Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.”进一步追查,其原因在于Bitmap.gradientFillRect,以及更上一层的Window_Confirmation.Window_Selectable.drawBackgroundRect;这说明了是渐变传入参数的问题,但我也没有自己定义传入任何渐变参数呀!
因此向大神们请教一下问题到底出在哪里;我问了deepseek它的解法完全不可行。另,我的各个窗口件长宽高都是随手写的,但我想应该不会是窗口件重叠造成的问题吧。
以下是代码内容:
- /*:
- * @target MZ
- * @plugindesc 物品合成系统 v1.0 - 支持多种配方和操作台的合成系统
- * @author Snowwolf
- *
- * @param RecipeFile
- * @text 配方文件
- * @desc 合成配方JSON文件的路径
- * @type string
- * @default data/SynthesisRecipe.json
- *
- * @help
- * 使用说明:
- * 1. 准备配方文件:在指定路径创建SynthesisRecipe.json文件
- * 2. 在事件中使用插件命令调用合成界面
- * 3. 或在脚本中使用Window_SynthesisSystem.open("stove")调用
- *
- * 插件命令:
- * OpenSynthesis workstationType - 打开指定类型的合成界面
- */
- (() => {
- // 插件参数
- const parameters = PluginManager.parameters('ItemSynthesisSystem');
- const recipeFile = parameters.RecipeFile || 'data/SynthesisRecipe.json';
-
- // 内部定义的操作台类型
- const WORKSTATIONS = {
- herbalist_table: { name: "炼金台", icon: 224 },
- anvil: { name: "铁砧", icon: 225 },
- stove: { name: "灶台", icon: 226 },
- sewing: { name: "缝纫台", icon: 227 }
- };
-
- // 合成系统核心类
- class SynthesisSystem {
- constructor() {
- this._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, 40);
- 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, 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 width = 400;
- const height = 250;
- const x = Graphics.boxWidth/2;
- const y = Graphics.boxHeight/2;
- const rect = new Rectangle(x, y, Graphics.boxWidth/2, Graphics.boxHeight);
-
- 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);
- this._recipeListWindow.activate();
- this._recipeListWindow.refresh();
- }
-
- onConfirmNo() {
- this.removeWindow(this._confirmationWindow);
- 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);
- 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) {
- super(rect);
- this._recipe = recipe;
- this.refresh();
- }
- makeCommandList() {
- this.addCommand("是", 'yes');
- this.addCommand("否", 'no');
- }
-
- refresh() {
- super.refresh();
- this.drawRecipeInfo();
-
- }
-
- drawRecipeInfo() {
- if (!this._recipe) return;
-
- // 绘制配方名称
- let y = this.lineHeight();
- this.drawText(`合成 ${this._recipe.name} 需要:`, 0, y, this.contentsWidth, 'center');
- y += this.lineHeight() * 1.5;
-
- // 绘制材料需求
- 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());
-
- // 绘制材料信息
- this.drawText(`${itemName} x${material.count} (现有:${currentCount})`, 0, y, this.contentsWidth, 'center');
- y += this.lineHeight();
- });
-
- // 绘制提示文本
- y += this.lineHeight();
- // this.changeTextColor(this.normalColor());
- this.drawText("要合成该物品吗?", 0, y, this.contentsWidth, 'center');
- }
-
- // 将命令按钮放在窗口底部
- itemRect(index) {
- const rect = super.itemRect(index);
- rect.y = this.contentsHeight - rect.height * 2;
- return rect;
- }
- }
-
- // 插件命令处理
- 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);
- }
- };
- })();
复制代码
以下为测试用的SynthesisRecipe文件内容:
- [
- {
- "id": "healing_potion_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": "healing_potion_2",
- "name": "二级金创药",
- "result": {
- "type": "item",
- "id": 9,
- "count": 2
- },
- "materials": [
- {
- "type": "item",
- "id": 7,
- "count": 2
- },
- {
- "type": "item",
- "id": 12,
- "count": 1
- }
- ],
- "workstation": "herbalist_table"
- },
- {
- "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",
- "requiredSwitch": 10
- }
- ]
复制代码 |
|