/*:
* @target MZ
* @plugindesc Port Investment for RPG MAKER MZ
* @author lemonhall
*
* @command showInvestment
* @text Show showInvestment
* @desc Displays the showInvestment of the port
*
* @arg url
* @type string
* @text URL
* @desc URL to be loaded in the web viewer.
* @default https://www.example.com
*
* @param closeButtonSize
* @type number
* @text Close Button Size
* @desc Size of the close button in pixels.
* @default 30
*
* @param closeButtonPosition
* @type select
* @text Close Button Position
* @desc Position of the close button.
* @default Top Right
* @option Top Left
* @option Top Center
* @option Top Right
* @option Bottom Left
* @option Bottom Center
* @option Bottom Right
*
* @help
* To open the web viewer, use the plugin command "Show Web Viewer" in events.
*/
(() => {
const pluginName = "ShowInvestment";
const parameters = PluginManager.parameters(pluginName);
PluginManager.registerCommand(pluginName, "showInvestment", args => {
SceneManager.push(Scene_ShowInvestment);
Scene_ShowInvestment.prototype.url = args.url;
// 我修改了Game_Interpreter的Plugin Command后,添加了eventCaller后,让Plugin在被调用时
// 能拿到正确的 event信息,方便在event里直接设置运行逻辑,或者让插件逻辑直接获取信息
//=====================================================================
// // Plugin Command
// Game_Interpreter.prototype.command357 = function(params) {
// console.log("IN Plugin Command [params]: ");
// // 对象的输出为这个样子
// // 0: "WebViewerMZ2"
// // 1: "showWebViewer"
// // 2: "Show Web Viewer"
// // 3: {url: "https://hsp.lemonhall.me/cards/index.html"}
// console.log(params);
// //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// //我个人增加的逻辑:
// params[3]["eventCaller"] = $dataMap.events[this._eventId];
// //检查一下增加的eventCaller是否正确加入了args
// console.log("IN Plugin Command params[3][eventCaller]: ");
// console.log(params[3]["eventCaller"]);
// //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//=====================================================================
Scene_ShowInvestment.prototype.eventCaller = args.eventCaller;
});
// Window_Command.prototype.refresh = function() {
// this.clearCommandList();
// this.makeCommandList();
// Window_Selectable.prototype.refresh.call(this);
// };
//Window_Command继承于Window_Selectable<--Window_Scrollable<---Window_Base
class Window_InvestmentCommand extends Window_Command {
makeCommandList () {
super.makeCommandList();
var enabled = true
this.addCommand("投资", "investment", enabled);
this.addCommand("取消", "cancel", enabled);
}
}
//Scene_MenuBase继承于Scene_Base
class Scene_ShowInvestment extends Scene_MenuBase {
create() {
super.create();
//showPicture = function(pictureId, name, origin, x, y, scaleX, scaleY, opacity, blendMode)
// console.log(name, origin, x, y, scaleX, scaleY, opacity, blendMode);
// Actor1_8 0 0 0 100 100 255 0
//$gameScreen.showPicture (1 ,"Actor1_8", 0 ,0 , 0, 100 ,100 , 255 ,0);
//以上的方法是不适合的,因为会被遮罩掉
//
//
//Window_Base.prototype.drawFace 这里有一个drawFace方法
//Window_Base继承于window,属于整个window的基类了
// prettier-ignore
// Window_Base.prototype.drawFace = function(
// faceName, faceIndex, x, y, width, height
// ) {
// //console.log("Window_Base.prototype.drawFace:");
// //console.log( faceName, faceIndex, x, y, width, height);
// // Actor1 0 5 3 144 129
// width = width || ImageManager.faceWidth;
// height = height || ImageManager.faceHeight;
// const bitmap = ImageManager.loadFace(faceName);
// const pw = ImageManager.faceWidth;
// const ph = ImageManager.faceHeight;
// const sw = Math.min(width, pw);
// const sh = Math.min(height, ph);
// const dx = Math.floor(x + Math.max(width - pw, 0) / 2);
// const dy = Math.floor(y + Math.max(height - ph, 0) / 2);
// const sx = Math.floor((faceIndex % 4) * pw + (pw - sw) / 2);
// const sy = Math.floor(Math.floor(faceIndex / 4) * ph + (ph - sh) / 2);
// this.contents.blt(bitmap, sx, sy, sw, sh, dx, dy);
// };
this.createCommandWindow();
//实验性的画个脸出来看看
//console.log( faceName, faceIndex, x, y, width, height);
//this._commandWindow.drawFace("Actor1",0,5,3,144,129);
//成功了,但是这个x和y啊,是一个相对于这个窗口的x,y,行吧,这也好
this.createGoldWindow();
this.createNPCWindow();
this._npcWindow.drawFace("Actor1",0,5,3,144,129);
this._npcWindow.update();
this._npcWindow.drawText("欢迎光临【"+this.eventCaller.name+"】",10,150);
this._npcWindow.drawText("您是要投资么?",10,200);
this._npcWindow.update();
this.createInvestmentWindow();
this._investmentWindow.drawText("您当前的投资额度为:0",10,0);
this._investmentWindow.update();
// Scene_Gameover.prototype.createBackground = function() {
// this._backSprite = new Sprite();
// this._backSprite.bitmap = ImageManager.loadSystem("GameOver");
// this.addChild(this._backSprite);
// };
// const spritePic = new Sprite_Picture();
// spritePic.bitmap = ImageManager.loadSystem("GameOver");
// console.log(spritePic);
// this.addChild(spritePic);
}
createInvestmentWindow = function() {
const rect = this.investmentWindowRect();
const investmentWindow = new Window_Base(rect);
this.addWindow(investmentWindow);
this._investmentWindow = investmentWindow;
}
investmentWindowRect = function() {
const ww = 500;
const wh = this.calcWindowHeight(1, true);
const wx = 50;
const wy = this.mainAreaTop()+this.mainAreaHeight();
return new Rectangle(wx, wy, ww, wh);
}
createNPCWindow = function() {
const rect = this.npcWindowRect();
const npcWindow = new Window_Base(rect);
this.addWindow(npcWindow);
this._npcWindow = npcWindow;
}
npcWindowRect = function() {
const ww = 500;
const wh = this.mainAreaHeight();
const wx = 50;
const wy = 50;
return new Rectangle(wx, wy, ww, wh);
}
createCommandWindow = function() {
const rect = this.commandWindowRect();
const commandWindow = new Window_InvestmentCommand(rect);
commandWindow.setHandler("investment", this.commandInvestment.bind(this));
commandWindow.setHandler("cancel", this.popScene.bind(this));
this.addWindow(commandWindow);
this._commandWindow = commandWindow;
}
commandWindowRect = function() {
// Scene_Base.prototype.mainCommandWidth = function() {
// return 240;
// };
const ww = this.mainCommandWidth();
// Scene_MenuBase.prototype.mainAreaHeight = function() {
// return Graphics.boxHeight - this.buttonAreaHeight() - this.helpAreaHeight();
// };
const wh = this.mainAreaHeight()
// Scene_Base.prototype.isRightInputMode = function() {
// return true;
// };
const wx = this.isRightInputMode() ? Graphics.boxWidth - ww : 0;
// Scene_MenuBase.prototype.mainAreaTop = function() {
// if (!this.isBottomHelpMode()) {
// return this.helpAreaBottom();
// } else if (this.isBottomButtonMode()) {
// return 0;
// } else {
// return this.buttonAreaBottom();
// }
// };
const wy = this.mainAreaTop();
return new Rectangle(wx, wy, ww, wh);
}
commandInvestment = function() {
console.log("commandInvestment is fired!!!");
SceneManager.pop();
}
createGoldWindow = function() {
const rect = this.goldWindowRect();
this._goldWindow = new Window_Gold(rect);
this.addWindow(this._goldWindow);
}
goldWindowRect = function() {
const ww = this.mainCommandWidth();
const wh = this.calcWindowHeight(1, true);
const wx = Graphics.boxWidth - ww;
const wy = this.mainAreaTop()+this.mainAreaHeight();
return new Rectangle(wx, wy, ww, wh);
}
// // Show Picture
// Game_Interpreter.prototype.command231 = function(params) {
// const point = this.picturePoint(params);
// // prettier-ignore
// $gameScreen.showPicture(
// params[0], params[1], params[2], point.x, point.y,
// params[6], params[7], params[8], params[9]
// );
// return true;
// };
//想显示人物立绘可以参考这个
// prettier-ignore
// Game_Screen.prototype.showPicture = function(
// pictureId, name, origin, x, y, scaleX, scaleY, opacity, blendMode
// ) {
// const realPictureId = this.realPictureId(pictureId);
// const picture = new Game_Picture();
// picture.show(name, origin, x, y, scaleX, scaleY, opacity, blendMode);
// this._pictures[realPictureId] = picture;
// };
}
})();
首先是:

窗体的绘制部分是:
createCommandWindow = function() {
const rect = this.commandWindowRect();
const commandWindow = new Window_InvestmentCommand(rect);
commandWindow.setHandler("investment", this.commandInvestment.bind(this));
commandWindow.setHandler("cancel", this.popScene.bind(this));
this.addWindow(commandWindow);
this._commandWindow = commandWindow;
}
commandWindowRect = function() {
// Scene_Base.prototype.mainCommandWidth = function() {
// return 240;
// };
const ww = this.mainCommandWidth();
// Scene_MenuBase.prototype.mainAreaHeight = function() {
// return Graphics.boxHeight - this.buttonAreaHeight() - this.helpAreaHeight();
// };
const wh = this.mainAreaHeight()
// Scene_Base.prototype.isRightInputMode = function() {
// return true;
// };
const wx = this.isRightInputMode() ? Graphics.boxWidth - ww : 0;
// Scene_MenuBase.prototype.mainAreaTop = function() {
// if (!this.isBottomHelpMode()) {
// return this.helpAreaBottom();
// } else if (this.isBottomButtonMode()) {
// return 0;
// } else {
// return this.buttonAreaBottom();
// }
// };
const wy = this.mainAreaTop();
return new Rectangle(wx, wy, ww, wh);
}
然后是:

createGoldWindow = function() {
const rect = this.goldWindowRect();
this._goldWindow = new Window_Gold(rect);
this.addWindow(this._goldWindow);
}
goldWindowRect = function() {
const ww = this.mainCommandWidth();
const wh = this.calcWindowHeight(1, true);
const wx = Graphics.boxWidth - ww;
const wy = this.mainAreaTop()+this.mainAreaHeight();
return new Rectangle(wx, wy, ww, wh);
}接着是:

createInvestmentWindow = function() {
const rect = this.investmentWindowRect();
const investmentWindow = new Window_Base(rect);
this.addWindow(investmentWindow);
this._investmentWindow = investmentWindow;
}
investmentWindowRect = function() {
const ww = 500;
const wh = this.calcWindowHeight(1, true);
const wx = 50;
const wy = this.mainAreaTop()+this.mainAreaHeight();
return new Rectangle(wx, wy, ww, wh);
}最后一部分是:

createNPCWindow = function() {
const rect = this.npcWindowRect();
const npcWindow = new Window_Base(rect);
this.addWindow(npcWindow);
this._npcWindow = npcWindow;
}
npcWindowRect = function() {
const ww = 500;
const wh = this.mainAreaHeight();
const wx = 50;
const wy = 50;
return new Rectangle(wx, wy, ww, wh);
}
==========================================
然后它们的入口是:
create() {
super.create();
this.createCommandWindow();
this.createGoldWindow();
this.createNPCWindow();
this._npcWindow.drawFace("Actor1",0,5,3,144,129);
this._npcWindow.update();
this._npcWindow.drawText("欢迎光临【"+this.eventCaller.name+"】",10,150);
this._npcWindow.drawText("您是要投资么?",10,200);
this._npcWindow.update();
this.createInvestmentWindow();
this._investmentWindow.drawText("您当前的投资额度为:0",10,0);
this._investmentWindow.update();
}等于是先画命令窗口,再画金币窗口,再画npc窗口,然后在npc窗口里画脸,并且写字
最后画投资窗口,并显示投资额度
==========================================================
// Window_Command.prototype.refresh = function() {
// this.clearCommandList();
// this.makeCommandList();
// Window_Selectable.prototype.refresh.call(this);
// };
//Window_Command继承于Window_Selectable<--Window_Scrollable<---Window_Base
class Window_InvestmentCommand extends Window_Command {
makeCommandList () {
super.makeCommandList();
var enabled = true
this.addCommand("投资", "investment", enabled);
this.addCommand("取消", "cancel", enabled);
}
}命令窗口里使用了Window_Command
//Window_Command继承于Window_Selectable<--Window_Scrollable<---Window_Base==========================================================
同时:
createCommandWindow = function() {
const rect = this.commandWindowRect();
const commandWindow = new Window_InvestmentCommand(rect);
commandWindow.setHandler("investment", this.commandInvestment.bind(this));
commandWindow.setHandler("cancel", this.popScene.bind(this));
this.addWindow(commandWindow);
this._commandWindow = commandWindow;
}配置了两个命令的监听函数:
commandInvestment = function() {
console.log("commandInvestment is fired!!!");
SceneManager.pop();
}其中投资命令要记得处理完后pop出场景管理器
==============================================

存储的化,在dataManager里引json文件就可以了
然后第二步:

其实是应该增添一个gameObject的
然后去操作$gameCitys这个对象【假设它已经存在了哈】

操作完了以后,在makeSave和extractSave这两个函数里,分别挂上你新添加的东西就行了
这个不能靠重载来实现
因为游戏机制里,DataManager你也看到了,不带原型链,所以它本质上不是一个类
而是一个上来就已经实例化了的单体
所以你没法重载它
暂时只能直接修改DataManager,这个稍后我再看看有什么技巧吧
==================================================================
这样,这个插件就实现了:
1、新建一个自己的场景:港口投资管理处
2、新建了四个窗口
3、与load/save联动来修改citys的数据
==================================================================
// Plugin Command
Game_Interpreter.prototype.command357 = function(params) {
console.log("IN Plugin Command [params]: ");
// 对象的输出为这个样子
// 0: "WebViewerMZ2"
// 1: "showWebViewer"
// 2: "Show Web Viewer"
// 3: {url: "https://hsp.lemonhall.me/cards/index.html"}
console.log(params);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//我个人增加的逻辑:
params[3]["eventCaller"] = $dataMap.events[this._eventId];
//检查一下增加的eventCaller是否正确加入了args
console.log("IN Plugin Command params[3][eventCaller]: ");
console.log(params[3]["eventCaller"]);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const pluginName = Utils.extractFileName(params[0]);
// 这里是callCommand的具体实现:
// PluginManager.callCommand = function(self, pluginName, commandName, args) {
// const key = pluginName + ":" + commandName;
// const func = this._commands[key];
// if (typeof func === "function") {
// func.bind(self)(args);
// }
// };
PluginManager.callCommand(this, pluginName, params[1], params[3]);
console.log("IN Plugin Command [this]: ");
// 这个时候,this就是 Game_Interpreter 本身了
// _branch: {}
// _characterId: 0
// _childInterpreter: null
// _comments: ""
// _depth: 0
// _eventId: 21
// _frameCount: 125
// _freezeChecker: 1
// _indent: 0
// _index: 1
// _list: (3) [{…}, {…}, {…}]
// _mapId: 1
// _waitCount: 0
// _waitMode: ""
console.log(this);
// 输出是:IN Plugin Command params[1]: showWebViewer
console.log("IN Plugin Command params[1]: "+params[1]);
console.log("IN Plugin Command params[3]: "+params[3]);
//实际上就是这个:{url: "https://hsp.lemonhall.me/cards/index.html"}
console.log(params[3]);
//使用$dataMap.events[21].name,可以得到当前地图上21号event的name
//所以更优雅的方式是,可以直接把$dataMap.events[21]这个对象,塞入params[3]里面去
//这样
return true;
};最后一个其实有点鸡肋
就是修改了Game_Interpreter.prototype.command357
给插件传参,直接把caller的event信息传给了插件

这样插件就可以直接这么使用eventCaller对象了
意思不大,但更加优雅了
这也是直接修改了引擎本身,要注意;