//=============================================================================
// SoulsBlacksmith.js
//=============================================================================
/*:
* @target MZ
* @plugindesc [v1.0] Sistema de upgrade de armas estilo Souls (Troca de IDs, Pedras de Forja e Ouro por Categoria).
* @author Você / Gemini
*
* @command OpenBlacksmith
* @text Open Blacksmith Menu
* @desc Opens the weapon upgrade interface.
*
* @param SmallStoneId
* @text Small Stone Item ID
* @type item
* @default 1
*
* @param MediumStoneId
* @text Medium Stone Item ID
* @type item
* @default 2
*
* @param LargeStoneId
* @text Large Stone Item ID
* @type item
* @default 3
*
* @param WeakMultiplier
* @text Weak Tier Gold Multiplier
* @type number
* @default 2
* @desc Multiplier for weak weapons (e.g., Base Gold * 2).
*
* @param MediumMultiplier
* @text Medium Tier Gold Multiplier
* @type number
* @default 5
* @desc Multiplier for medium weapons (e.g., Base Gold * 5).
*
* @param StrongMultiplier
* @text Strong Tier Gold Multiplier
* @type number
* @default 9
* @desc Multiplier for strong weapons (e.g., Base Gold * 9).
*
* @param TextUpgradeCommand
* @text Text: Upgrade Button
* @default Upgrade
*
* @param TextCancelCommand
* @text Text: Cancel Button
* @default Cancel
*
* @param TextRequiredMaterials
* @text Text: Materials Section
* @default Required Materials:
*
* @param TextGoldCost
* @text Text: Cost Section
* @default Upgrade Cost:
*
* @param TextMaxLevel
* @text Text: Max Level Label
* @default MAX
*
* @param TextWeaponListTitle
* @text Text: Menu Title
* @default Weapon Reinforcement
*
* @param LevelSettings
* @text Level Upgrade Settings
* @type struct<LevelConfig>[]
* @default ["{\"TargetLevel\":\"2\",\"StoneType\":\"1\",\"StoneAmount\":\"1\",\"BaseGold\":\"100\"}","{\"TargetLevel\":\"3\",\"StoneType\":\"1\",\"StoneAmount\":\"2\",\"BaseGold\":\"150\"}","{\"TargetLevel\":\"4\",\"StoneType\":\"1\",\"StoneAmount\":\"3\",\"BaseGold\":\"200\"}","{\"TargetLevel\":\"5\",\"StoneType\":\"2\",\"StoneAmount\":\"1\",\"BaseGold\":\"300\"}","{\"TargetLevel\":\"6\",\"StoneType\":\"2\",\"StoneAmount\":\"2\",\"BaseGold\":\"400\"}","{\"TargetLevel\":\"7\",\"StoneType\":\"2\",\"StoneAmount\":\"3\",\"BaseGold\":\"500\"}","{\"TargetLevel\":\"8\",\"StoneType\":\"3\",\"StoneAmount\":\"1\",\"BaseGold\":\"700\"}","{\"TargetLevel\":\"9\",\"StoneType\":\"3\",\"StoneAmount\":\"2\",\"BaseGold\":\"900\"}","{\"TargetLevel\":\"10\",\"StoneType\":\"3\",\"StoneAmount\":\"3\",\"BaseGold\":\"1200\"}"]
*/
/*~struct~LevelConfig:
* @param TargetLevel
* @text Upgrade to Level
* @type number
* @min 2
* @max 10
* * @param StoneType
* @text Stone Type Needed
* @type select
* @option Small
* @value 1
* @option Medium
* @value 2
* @option Large
* @value 3
* @default 1
* * @param StoneAmount
* @text Stone Amount Needed
* @type number
* @default 1
* * @param BaseGold
* @text Base Gold Cost
* @type number
* @default 100
*/
(function() {
'use strict';
const pluginName = "SoulsBlacksmith";
const parameters = PluginManager.parameters(pluginName);
const stoneIds = {
1: Number(parameters['SmallStoneId'] || 1),
2: Number(parameters['MediumStoneId'] || 2),
3: Number(parameters['LargeStoneId'] || 3)
};
const multipliers = {
'weak': Number(parameters['WeakMultiplier'] || 2),
'medium': Number(parameters['MediumMultiplier'] || 5),
'strong': Number(parameters['StrongMultiplier'] || 9)
};
const texts = {
upgrade: parameters['TextUpgradeCommand'] || "Upgrade",
cancel: parameters['TextCancelCommand'] || "Cancel",
materials: parameters['TextRequiredMaterials'] || "Required Materials:",
gold: parameters['TextGoldCost'] || "Upgrade Cost:",
max: parameters['TextMaxLevel'] || "MAX",
title: parameters['TextWeaponListTitle'] || "Weapon Reinforcement"
};
let levelConfigs = {};
try {
if (parameters['LevelSettings']) {
JSON.parse(parameters['LevelSettings']).forEach(str => {
let cfg = JSON.parse(str);
levelConfigs[Number(cfg.TargetLevel)] = {
stoneType: Number(cfg.StoneType),
stoneAmount: Number(cfg.StoneAmount),
baseGold: Number(cfg.BaseGold)
};
});
}
} catch(e) {
console.error("SoulsBlacksmith: Error parsing level settings.");
}
PluginManager.registerCommand(pluginName, "OpenBlacksmith", () => {
SceneManager.push(Scene_Blacksmith);
});
// Helper functions to read weapon tags
function getWeaponLevel(item) {
return item && item.meta.WeaponLevel ? Number(item.meta.WeaponLevel) : 1;
}
function getWeaponTier(item) {
return item && item.meta.WeaponTier ? item.meta.WeaponTier.trim().toLowerCase() : 'weak';
}
function getUpgradeId(item) {
return item && item.meta.UpgradeId ? Number(item.meta.UpgradeId) : 0;
}
function getUpgradeCost(item) {
const nextLvl = getWeaponLevel(item) + 1;
const cfg = levelConfigs[nextLvl];
if (!cfg) return { gold: 0, stoneItem: null, stoneAmount: 0 };
const tier = getWeaponTier(item);
const mult = multipliers[tier] || 2;
const goldCost = cfg.baseGold * mult;
const stoneItem = $dataItems[stoneIds[cfg.stoneType]];
return {
gold: goldCost,
stoneItem: stoneItem,
stoneAmount: cfg.stoneAmount
};
}
//=============================================================================
// UI Windows (Sized for 816x624)
//=============================================================================
class Window_BlacksmithTitle extends Window_Base {
initialize(rect) {
super.initialize(rect);
this.refresh();
}
refresh() {
this.contents.clear();
this.drawText(texts.title, 0, 0, this.innerWidth, 'center');
}
}
class Window_BlacksmithWeaponList extends Window_Selectable {
initialize(rect) {
super.initialize(rect);
this.makeItemList();
this.refresh();
this.select(0);
}
maxItems() { return this._data ? this._data.length : 0; }
item() { return this._data && this.index() >= 0 ? this._data[this.index()] : null; }
makeItemList() {
this._data = [];
// Weapons in inventory
$gameParty.weapons().forEach(wpn => {
if (wpn.meta.WeaponLevel || wpn.meta.UpgradeId) {
this._data.push({ item: wpn, actor: null, slotId: -1 });
}
});
// Equipped weapons
$gameParty.members().forEach(actor => {
actor.equips().forEach((wpn, slotId) => {
if (wpn && DataManager.isWeapon(wpn) && (wpn.meta.WeaponLevel || wpn.meta.UpgradeId)) {
this._data.push({ item: wpn, actor: actor, slotId: slotId });
}
});
});
}
drawItem(index) {
const data = this._data[index];
if (!data) return;
const rect = this.itemLineRect(index);
this.resetFontSettings();
// Draw name and icon
this.drawItemName(data.item, rect.x, rect.y, rect.width - 100);
// Draw level tag or MAX
const lvl = getWeaponLevel(data.item);
const upgradeId = getUpgradeId(data.item);
this.changeTextColor(ColorManager.systemColor());
if (upgradeId === 0 || lvl >= 10) {
this.drawText(`[${texts.max}]`, rect.x + rect.width - 80, rect.y, 80, 'right');
} else {
this.drawText(`+${lvl}`, rect.x + rect.width - 80, rect.y, 80, 'right');
}
}
isEnabled(index) {
const data = this._data[index];
if (!data) return false;
const upgradeId = getUpgradeId(data.item);
if (upgradeId <= 0) return false;
const cost = getUpgradeCost(data.item);
if ($gameParty.gold() < cost.gold) return false;
if (cost.stoneItem && $gameParty.numItems(cost.stoneItem) < cost.stoneAmount) return false;
return true;
}
}
class Window_BlacksmithStatus extends Window_Base {
setWeaponData(data) {
this._data = data;
this.refresh();
}
refresh() {
this.contents.clear();
if (!this._data) return;
const currentWpn = this._data.item;
const upgradeId = getUpgradeId(currentWpn);
const nextWpn = upgradeId > 0 ? $dataWeapons[upgradeId] : null;
this.resetFontSettings();
this.drawText(currentWpn.name, 0, 0, this.innerWidth);
let y = 50;
const paramNames = [TextManager.param(2), TextManager.param(3), TextManager.param(4), TextManager.param(5)];
const paramIds = [2, 3, 4, 5]; // ATK, DEF, MAT, MDF
paramIds.forEach((id, index) => {
const curVal = currentWpn.params[id];
const nextVal = nextWpn ? nextWpn.params[id] : curVal;
if (curVal > 0 || (nextWpn && nextVal > 0)) {
this.changeTextColor(ColorManager.systemColor());
this.drawText(paramNames[index], 10, y, 120);
this.changeTextColor(ColorManager.normalColor());
this.drawText(curVal, 140, y, 50, 'right');
if (nextWpn && nextVal !== curVal) {
this.changeTextColor(ColorManager.systemColor());
this.drawText("\u2192", 200, y, 30, 'center');
this.changeTextColor(ColorManager.powerUpColor());
this.drawText(nextVal, 240, y, 50, 'right');
}
y += 35;
}
});
}
}
class Window_BlacksmithCost extends Window_Base {
setWeaponData(data) {
this._data = data;
this.refresh();
}
refresh() {
this.contents.clear();
if (!this._data) return;
const currentWpn = this._data.item;
const upgradeId = getUpgradeId(currentWpn);
if (upgradeId <= 0) {
this.drawText(texts.max, 0, this.innerHeight / 2 - 15, this.innerWidth, 'center');
return;
}
const cost = getUpgradeCost(currentWpn);
// Draw Stones
this.changeTextColor(ColorManager.systemColor());
this.drawText(texts.materials, 10, 10, this.innerWidth - 20);
this.resetFontSettings();
if (cost.stoneItem) {
this.drawItemName(cost.stoneItem, 20, 45, 300);
const ownedStones = $gameParty.numItems(cost.stoneItem);
this.changeTextColor(ownedStones >= cost.stoneAmount ? ColorManager.normalColor() : ColorManager.powerDownColor());
this.drawText(`${ownedStones} / ${cost.stoneAmount}`, 330, 45, 100, 'left');
}
// Draw Gold
this.changeTextColor(ColorManager.systemColor());
this.drawText(texts.gold, 480, 10, 300);
this.resetFontSettings();
const currentGold = $gameParty.gold();
this.changeTextColor(currentGold >= cost.gold ? ColorManager.normalColor() : ColorManager.powerDownColor());
this.drawText(`${cost.gold} ${TextManager.currencyUnit()}`, 480, 45, 250, 'left');
}
}
class Window_BlacksmithConfirm extends Window_Command {
makeCommandList() {
this.addCommand(texts.upgrade, 'confirm');
this.addCommand(texts.cancel, 'cancel');
}
}
//=============================================================================
// Scene_Blacksmith
//=============================================================================
class Scene_Blacksmith extends Scene_MenuBase {
create() {
super.create();
this.createAllWindows();
}
createAllWindows() {
// Header
this._titleWindow = new Window_BlacksmithTitle(new Rectangle(0, 0, Graphics.boxWidth, 60));
this.addWindow(this._titleWindow);
// Left Side: List
const listRect = new Rectangle(0, 60, 430, 380);
this._listWindow = new Window_BlacksmithWeaponList(listRect);
this._listWindow.setHandler('ok', this.onWeaponOk.bind(this));
this._listWindow.setHandler('cancel', this.popScene.bind(this));
this._listWindow.setHandler('select', this.onWeaponSelect.bind(this));
this.addWindow(this._listWindow);
// Right Side: Status
const statusRect = new Rectangle(430, 60, Graphics.boxWidth - 430, 380);
this._statusWindow = new Window_BlacksmithStatus(statusRect);
this.addWindow(this._statusWindow);
// Bottom Side: Materials & Gold
const costRect = new Rectangle(0, 440, Graphics.boxWidth, Graphics.boxHeight - 440);
this._costWindow = new Window_BlacksmithCost(costRect);
this.addWindow(this._costWindow);
// Floating Small Confirmation Window
const confRect = new Rectangle(Graphics.boxWidth / 2 - 120, Graphics.boxHeight / 2 - 60, 240, this.calcWindowHeight(2, true));
this._confirmWindow = new Window_BlacksmithConfirm(confRect);
this._confirmWindow.setHandler('confirm', this.onUpgradeConfirm.bind(this));
this._confirmWindow.setHandler('cancel', this.onUpgradeCancel.bind(this));
this._confirmWindow.hide();
this._confirmWindow.deactivate();
this.addWindow(this._confirmWindow);
this.onWeaponSelect();
}
onWeaponSelect() {
const data = this._listWindow.item();
if (this._statusWindow) this._statusWindow.setWeaponData(data);
if (this._costWindow) this._costWindow.setWeaponData(data);
}
onWeaponOk() {
if (this._listWindow.isEnabled(this._listWindow.index())) {
SoundManager.playOk();
this._confirmWindow.show();
this._confirmWindow.activate();
this._confirmWindow.select(0);
} else {
SoundManager.playBuzzer();
this._listWindow.activate();
}
}
onUpgradeConfirm() {
const data = this._listWindow.item();
if (!data) return;
const currentWpn = data.item;
const upgradeId = getUpgradeId(currentWpn);
const nextWpn = $dataWeapons[upgradeId];
const cost = getUpgradeCost(currentWpn);
// Spend Resources
$gameParty.loseGold(cost.gold);
if (cost.stoneItem) {
$gameParty.loseItem(cost.stoneItem, cost.stoneAmount);
}
// Swap Weapons (Handles Equipment beautifully)
if (data.actor && data.slotId >= 0) {
$gameParty.gainItem(nextWpn, 1);
data.actor.changeEquip(data.slotId, nextWpn);
$gameParty.loseItem(currentWpn, 1); // Vaporizes the old weak item from inventory
} else {
$gameParty.gainItem(nextWpn, 1);
$gameParty.loseItem(currentWpn, 1);
}
SoundManager.playUseItem();
// Redraw and Reset
this._confirmWindow.hide();
this._confirmWindow.deactivate();
this._listWindow.makeItemList();
this._listWindow.refresh();
this._listWindow.activate();
this.onWeaponSelect();
}
onUpgradeCancel() {
this._confirmWindow.hide();
this._confirmWindow.deactivate();
this._listWindow.activate();
}
}
})();
To embed this project on your website, copy the following code and paste it into your website's HTML: