ultimate-angel-zerachiel/www/js/plugins/CraftingSystem.js
2024-01-17 12:05:32 -06:00

793 lines
24 KiB
JavaScript

//=============================================================================
// CraftingSystem.js
//=============================================================================
/*:
* @plugindesc Craft items, weapons and armors based on categorized recipe books.
* @author Julian "Szyu" Heinen
* @version 1.4
*
* @param Categories
* @desc The names of the categories.
* @default Blacksmith, Alchemy
*
* @param CraftingSounds
* @desc SE file names of sounds after creating an item for each category.
* @default Sword2, Ice4
*
* @param Price Text
* @desc Text used for item's price in status display
* @default Price
*
* @param Equip Text
* @desc Text used for item's equipment type in status display
* @default Equip
*
* @param Type Text
* @desc Text used for item's equipment type in status display
* @default Type
*
* @param Ingredients Text
* @desc Text used for indicating an item's crafting ingredients
* @default Ingredients:
*
* @param Currency Text
* @desc Text used for currency ingredients
* @default Currency
*
* @param Item Crafted Text
* @desc Text used after crafting an item
* @default Item crafted:
*
*
* @help
*
* Plugin Command:
* CraftingSystem open 0 # Opens the crafting scene for category #0
* CraftingSystem add_recipe 5: w3 # Adds the recipe of weapon #3 to recipe book #5
* CraftingSystem remove_recipe 5: a1 # Removes the recipe of armor #1 from recipe book #5
*
* Defining recipes for items, weapons and armors in their notes:
* <recipe>
* i: 1, 5 # requires 5 of item #1
* w: 3, 2 # requires 2 of weapon #3
* a: 2, 5 # requires 5 of armor #2
* c: 1000 # requires 1000 of currency
* </recipe>
*
* Defining recipe books (only key items) in their notes:
* <recipe_book>
* category: x # recipe book is of category #x
* i: 1, 3, 4 # recipe book contains the recipes of items #1, #3 and #4
* w: 3 # recipe book contains the recipes of weapon #3
* a: 2, 1 # recipe book contains the recipes of armors #1 and #2
* </recipe_book>
*
*
* To switch between ingredients display and status display, use the Q and W keys.
*/
(function () {
var parameters = PluginManager.parameters("CraftingSystem");
var categories = parameters["Categories"]
.replace(/^\s+|\s+$/gm, "")
.split(",") || ["Blacksmithing", "Alchemy"];
var craftingSounds = parameters["CraftingSounds"]
.replace(/^\s+|\s+$/gm, "")
.split(",") || ["Sword2", "Ice4"];
//var animations = parameters['Animations'].replace(/^\s+|\s+$/gm,'').split(',').map(Number) || [12, 13];
var priceText = String(parameters["Price Text"] || "Price");
var equipText = String(parameters["Equip Text"] || "Equip");
var typeText = String(parameters["Type Text"] || "Type");
var ingredientsText = String(
parameters["Ingredients Text"] || "Ingredients:"
);
var currencyText = String(parameters["Currency Text"] || "Currency");
var itemCraftedText = String(
parameters["Item Crafted Text"] || "Item crafted:"
);
/*----------------------------------------------
* Game_Interpreter
*---------------------------------------------*/
var _szcrsy_Game_Interpreter_pluginCommand =
Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
_szcrsy_Game_Interpreter_pluginCommand.call(this, command, args);
if (command == "CraftingSystem") {
switch (args[0]) {
case "open":
SceneManager.push(Scene_CraftingMenu);
SceneManager.prepareNextScene(args[1]);
break;
case "add_recipe":
this.addRecipes(args.splice(1, args.length - 1));
break;
case "remove_recipe":
this.removeRecipes(args.splice(1, args.length - 1));
break;
}
}
};
Game_Interpreter.prototype.addRecipes = function (args) {
var book = $dataItems[parseInt(args[0])];
var item;
var regex;
if (book._recipe_book == null) return;
for (var i = 1; i < args.length; i++) {
regex = args[i].match(/([iwa])(\d+)/i);
switch (regex[1]) {
case "i":
item = $dataItems[parseInt(regex[2])];
break;
case "w":
item = $dataWeapons[parseInt(regex[2])];
break;
case "a":
item = $dataArmors[parseInt(regex[2])];
break;
}
if (item._ingredients == null) continue;
if (
book._recipe_book["recipes"].filter(function (obj) {
return obj == item;
}).length > 0
)
continue;
book._recipe_book["recipes"].push(item);
}
};
Game_Interpreter.prototype.removeRecipes = function (args) {
var book = $dataItems[parseInt(args[0])];
var item;
var regex;
if (book._recipe_book == null) return;
for (var i = 1; i < args.length; i++) {
regex = args[i].match(/([iwa])(\d+)/i);
switch (regex[1]) {
case "i":
item = $dataItems[parseInt(regex[2])];
break;
case "w":
item = $dataWeapons[parseInt(regex[2])];
break;
case "a":
item = $dataArmors[parseInt(regex[2])];
break;
}
if (item._ingredients == null) continue;
if (
book._recipe_book["recipes"].filter(function (obj) {
return obj == item;
}).length == 0
)
continue;
book._recipe_book["recipes"].splice(
book._recipe_book["recipes"].indexOf(item),
1
);
}
};
/*----------------------------------------------
* DataManager
*---------------------------------------------*/
var _szcrsy_DataManager_createGameObjects = DataManager.createGameObjects;
DataManager.createGameObjects = function () {
_szcrsy_DataManager_createGameObjects.call(this);
// Create recipe book object
this.load_recipeBooks();
this.load_ingredientLists();
};
DataManager.load_recipeBooks = function () {
$dataItems.forEach(function (item) {
if (item == null) {
return;
}
item._recipe_book = null;
if (item.note.match(/<recipe_book>[\s\S]*<\/recipe_book>/m)) {
item._recipe_book = { recipes: [] };
var cat;
// check if category is correct
if ((cat = item.note.match(/category:\s*(\d+)/m))) {
item._recipe_book["category"] = parseInt(cat[1]);
//now item is sure to be a recipe book with correct category
var rec;
var db;
item.note
.match(/([iwa]:\s*[\d+,\s]*)/gim)
.forEach(function (recipe_line) {
rec = recipe_line.match(/([iwa]):\s*([\d+,\s]*)/i);
switch (rec[1]) {
case "w":
db = $dataWeapons;
break;
case "a":
db = $dataArmors;
break;
case "i":
db = $dataItems;
break;
}
rec[2].split(",").forEach(function (id) {
item._recipe_book["recipes"].push(db[parseInt(id)]);
}, this);
}, this);
}
}
}, this);
};
DataManager.load_ingredientLists = function () {
var dbs = [$dataItems, $dataWeapons, $dataArmors];
dbs.forEach(function (db) {
db.filter(function (obj) {
return obj != null;
}).forEach(function (item) {
item._ingredients = null;
if (item.note.match(/<recipe>[\s\S]*<\/recipe>/gim)) {
item._ingredients = [];
item.note
.match(/([iwa]:\s*\d+,\s*\d+|[c]:\s*\d+)/gim)
.forEach(function (ing_line) {
var ing = ing_line.match(
/([iwa]):\s*(\d+),\s*(\d+)|([c]):\s*(\d+)/i
);
var ing_db;
var needed;
if (ing[1] != null) {
switch (ing[1]) {
case "w":
ing_db = $dataWeapons[parseInt(ing[2])];
break;
case "a":
ing_db = $dataArmors[parseInt(ing[2])];
break;
case "i":
ing_db = $dataItems[parseInt(ing[2])];
break;
}
} else {
if (ing[4] == "c") {
ing_db = currencyText;
}
}
if (ing_db == currencyText) {
needed = parseInt(ing[5]);
} else {
needed = parseInt(ing[3]);
}
item._ingredients.push({ item: ing_db, amount: needed });
}, this);
}
}, this);
}, this);
};
var _szcrsy_DataManager_makeSaveContents = DataManager.makeSaveContents;
DataManager.makeSaveContents = function () {
// A save data does not contain $gameTemp, $gameMessage, and $gameTroop.
var contents = _szcrsy_DataManager_makeSaveContents.call(this);
var recipe_books = {};
$dataItems
.filter(function (item) {
return item != null && item._recipe_book != null;
})
.forEach(function (item) {
var rb_ids = [];
item._recipe_book.recipes.forEach(function (recipe) {
if (DataManager.isItem(recipe)) rb_ids.push("i" + recipe.id);
else if (DataManager.isWeapon(recipe)) rb_ids.push("w" + recipe.id);
else if (DataManager.isArmor(recipe)) rb_ids.push("a" + recipe.id);
}, this);
recipe_books[item.id] = rb_ids;
}, this);
contents.recipe_books = recipe_books;
return contents;
};
var _szcrsy_DataManager_extractSaveContents = DataManager.extractSaveContents;
DataManager.extractSaveContents = function (contents) {
_szcrsy_DataManager_extractSaveContents.call(this, contents);
var recipe_books = contents.recipe_books;
var rex;
for (var key in recipe_books) {
$dataItems[key]._recipe_book["recipes"] = [];
recipe_books[key].forEach(function (book) {
rex = book.match(/([iwa])(\d+)/i);
switch (rex[1]) {
case "i":
$dataItems[key]._recipe_book["recipes"].push(
$dataItems[parseInt(rex[2])]
);
break;
case "w":
$dataItems[key]._recipe_book["recipes"].push(
$dataWeapons[parseInt(rex[2])]
);
break;
case "a":
$dataItems[key]._recipe_book["recipes"].push(
$dataArmors[parseInt(rex[2])]
);
break;
}
}, this);
//console.log($dataItems[key]);
}
};
/*----------------------------------------------
* Scene_CraftingMenu
*---------------------------------------------*/
function Scene_CraftingMenu() {
this.initialize.apply(this, arguments);
}
Scene_CraftingMenu.prototype = Object.create(Scene_MenuBase.prototype);
Scene_CraftingMenu.prototype.constructor = Scene_CraftingMenu;
Scene_CraftingMenu.prototype.initialize = function () {
Scene_MenuBase.prototype.initialize.call(this);
};
Scene_CraftingMenu.prototype.prepare = function (category) {
this._category = category;
};
Scene_CraftingMenu.prototype.create = function () {
Scene_MenuBase.prototype.create.call(this);
// Create category window
this._categoryWindow = new Window_CraftingCategory(this._category);
this.addWindow(this._categoryWindow);
// Create item window
this._indexWindow = new Window_CraftingItems(
0,
this._categoryWindow.height,
288,
Graphics.height - this._categoryWindow.height,
this._category
);
this._indexWindow.setHandler("cancel", this.popScene.bind(this));
this._indexWindow.setHandler("ok", this.onCraft.bind(this));
this.addWindow(this._indexWindow);
// Create Item Status Window
var swy = this._indexWindow.y + this._indexWindow.height;
this._statusWindow = new Window_CraftingItemStatus(
this._indexWindow.width,
this._categoryWindow.height,
Graphics.width - this._indexWindow.width
);
this.addWindow(this._statusWindow);
this._indexWindow.setStatusWindow(this._statusWindow);
// Create Item Ingredients window
this._ingredientsWindow = new Window_CraftingIngredients(
this._indexWindow.width,
this._statusWindow.y + this._statusWindow.height,
500,
Graphics.height - this._statusWindow.y - this._statusWindow.height
);
this.addWindow(this._ingredientsWindow);
this._indexWindow.setIngredientsWindow(this._ingredientsWindow);
//this._indexWindow.setHandler('pagedown', this.showStatus.bind(this)); // W
this._messageWindow = new Window_Message();
this.addWindow(this._messageWindow);
this._messageWindow.subWindows().forEach(function (window) {
this.addWindow(window);
}, this);
this._activeWindow = 0;
};
Scene_CraftingMenu.prototype.onCraft = function () {
// Create crafting sound
var craftingSound = new Object();
craftingSound.name = craftingSounds[this._category];
craftingSound.pan = 0;
craftingSound.pitch = 100;
craftingSound.volume = 90;
AudioManager.playSe(craftingSound); // play crafting sound
$gameParty.gainItem(this._indexWindow.item(), 1);
this.loseIngredients();
// Show gain item Message
$gameMessage.setBackground(0);
$gameMessage.setPositionType(1) - 100;
$gameMessage.add(itemCraftedText + "\n" + this._indexWindow.item().name);
};
/*
Scene_CraftingMenu.prototype.showStatus = function(){
if (this._activeWindow !== 1){
var sw = this._statusWindow;
var iw = this._ingredientsWindow;
iw.move(Graphics.boxWidth,iw.y, iw.width, iw.height);
sw.move(0, sw.y, sw.width, sw.height);
this._activeWindow = 1;
this._indexWindow.setHandler('pageup', this.showIngredients.bind(this)); // Q
delete this._indexWindow._handlers['pagedown'];
}
this._indexWindow.activate();
};
Scene_CraftingMenu.prototype.showIngredients = function(){
if (this._activeWindow !== 0){
var sw = this._statusWindow;
var iw = this._ingredientsWindow;
sw.move(-Graphics.boxWidth, sw.y, sw.width, sw.height);
iw.move(0,iw.y, iw.width, iw.height);
this._activeWindow = 0;
this._indexWindow.setHandler('pagedown', this.showStatus.bind(this)); // W
delete this._indexWindow._handlers['pageup'];
}
this._indexWindow.activate();
};
*/
Scene_CraftingMenu.prototype.loseIngredients = function () {
var item = this._indexWindow.item();
var ing;
var db;
var needed;
item._ingredients.forEach(function (ing) {
needed = ing["amount"];
if (ing["item"] == currencyText) {
$gameParty.loseGold(needed);
} else {
$gameParty.loseItem(ing["item"], needed);
}
}, this);
this._ingredientsWindow.refresh();
};
/*----------------------------------------------
* Window_CraftingCategory
*---------------------------------------------*/
function Window_CraftingCategory() {
this.initialize.apply(this, arguments);
}
Window_CraftingCategory.prototype = Object.create(Window_Base.prototype);
Window_CraftingCategory.prototype.constructor = Window_CraftingCategory;
Window_CraftingCategory.prototype.initialize = function (category) {
this._category = category;
Window_Base.prototype.initialize.call(
this,
0,
0,
Graphics.boxWidth,
this.fittingHeight(1)
);
this.refresh();
};
Window_CraftingCategory.prototype.refresh = function () {
this.drawText(
categories[this._category],
0,
0,
this.contents.width,
this.lineHeight(),
"center"
);
};
/*----------------------------------------------
* Window_CraftingItems
*---------------------------------------------*/
function Window_CraftingItems() {
this.initialize.apply(this, arguments);
}
Window_CraftingItems.prototype = Object.create(Window_Selectable.prototype);
Window_CraftingItems.prototype.constructor = Window_CraftingItems;
Window_CraftingItems.lastTopRow = 0;
Window_CraftingItems.lastIndex = 0;
Window_CraftingItems.prototype.initialize = function (x, y, w, h, category) {
this._category = parseInt(category);
Window_Selectable.prototype.initialize.call(this, x, y, w, h);
this.refresh();
this.setTopRow(Window_CraftingItems.lastTopRow);
this.select(Window_CraftingItems.lastIndex);
this.activate();
};
Window_CraftingItems.prototype.maxCols = function () {
return 1;
};
Window_CraftingItems.prototype.maxItems = function () {
return this._list ? this._list.length : 0;
};
Window_CraftingItems.prototype.setStatusWindow = function (statusWindow) {
this._statusWindow = statusWindow;
this.updateStatus();
};
Window_CraftingItems.prototype.setIngredientsWindow = function (
ingredientsWindow
) {
this._ingredientsWindow = ingredientsWindow;
this.updateIngredients();
};
Window_CraftingItems.prototype.update = function () {
if (!$gameMessage.isBusy()) {
Window_Selectable.prototype.update.call(this);
this.updateStatus();
this.updateIngredients();
}
};
Window_CraftingItems.prototype.updateStatus = function () {
if (this._statusWindow) {
var item = this._list[this.index()];
this._statusWindow.setItem(item);
}
};
Window_CraftingItems.prototype.updateIngredients = function () {
if (this._ingredientsWindow) {
var item = this._list[this.index()];
this._ingredientsWindow.setItem(item);
}
};
Window_CraftingItems.prototype.refresh = function () {
var i, item;
var cat, c2;
this._list = [];
cat = parseInt(this._category);
$gameParty
.allItems()
.filter(function (item) {
return (
item._recipe_book != null &&
cat === parseInt(item._recipe_book["category"])
);
})
.forEach(function (item) {
item._recipe_book.recipes.forEach(function (rec_item) {
this._list.push(rec_item);
}, this);
}, this);
this.createContents();
this.drawAllItems();
};
Window_CraftingItems.prototype.drawItem = function (index) {
var item = this._list[index];
var rect = this.itemRect(index);
var width = rect.width - this.textPadding();
this.drawItemName(item, rect.x, rect.y, width);
};
Window_CraftingItems.prototype.processCancel = function () {
Window_Selectable.prototype.processCancel.call(this);
Window_CraftingItems.lastTopRow = this.topRow();
Window_CraftingItems.lastIndex = this.index();
};
Window_CraftingItems.prototype.processOk = function () {
if (this.itemIngredientsMet()) {
//this.playOkSound();
this.updateInputData();
this.callOkHandler();
} else {
this.playBuzzerSound();
}
};
Window_CraftingItems.prototype.item = function () {
var index = this.index();
return this._list && index >= 0 ? this._list[index] : null;
};
Window_CraftingItems.prototype.itemIngredientsMet = function () {
var item = this.item();
var met = true;
if (item == null) return false;
var existingCount = 0,
needed = 0;
item._ingredients.forEach(function (ing) {
needed = ing["amount"];
if (ing["item"] == currencyText) {
existingCount = $gameParty.gold();
} else {
existingCount = $gameParty.numItems(ing["item"]);
}
//console.log('ex: ' + existingCount + '; needed: ' + needed + '; RESULT: ' + (existingCount < needed));
if (existingCount < needed) {
met = false;
}
}, this);
return met;
};
/*----------------------------------------------
* Window_CraftingItemStatus
*---------------------------------------------*/
function Window_CraftingItemStatus() {
this.initialize.apply(this, arguments);
}
Window_CraftingItemStatus.prototype = Object.create(Window_Base.prototype);
Window_CraftingItemStatus.prototype.constructor = Window_CraftingItemStatus;
Window_CraftingItemStatus.prototype.initialize = function (x, y, width) {
Window_Base.prototype.initialize.call(
this,
x,
y,
width,
this.fittingHeight(6)
);
};
Window_CraftingItemStatus.prototype.setItem = function (item) {
if (this._item !== item) {
this._item = item;
this.refresh();
}
};
Window_CraftingItemStatus.prototype.refresh = function () {
var item = this._item;
var x = 0;
var y = 0;
var lineHeight = this.lineHeight();
var width = this.contents.width - this.textPadding() * 2;
this.contents.clear();
if (item == null) {
return;
}
this.drawItemName(item, x, y);
x = this.textPadding();
y = lineHeight + this.textPadding();
var price = item.price > 0 ? item.price : "-";
this.changeTextColor(this.systemColor());
this.drawText(priceText, x, y, 120);
this.resetTextColor();
this.drawText(price, x + 120, y, 120, "right");
y += lineHeight;
if (DataManager.isWeapon(item) || DataManager.isArmor(item)) {
var etype = $dataSystem.equipTypes[item.etypeId];
this.changeTextColor(this.systemColor());
this.drawText(equipText, x, y, 120);
this.resetTextColor();
this.drawText(etype, x + 120, y, 120, "right");
y += lineHeight;
var type;
if (DataManager.isWeapon(item)) {
type = $dataSystem.weaponTypes[item.wtypeId];
} else {
type = $dataSystem.armorTypes[item.atypeId];
}
this.changeTextColor(this.systemColor());
this.drawText(typeText, x, y, 120);
this.resetTextColor();
this.drawText(type, x + 120, y, 120, "right");
x = this.textPadding() + 300;
y = lineHeight + this.textPadding();
for (var i = 2; i < 6; i++) {
this.changeTextColor(this.systemColor());
this.drawText(TextManager.param(i), x, y, 160);
this.resetTextColor();
this.drawText(item.params[i], 0, y, width, "right");
y += lineHeight;
}
}
};
/*----------------------------------------------
* Window_CraftingIngredients
*---------------------------------------------*/
function Window_CraftingIngredients() {
this.initialize.apply(this, arguments);
}
Window_CraftingIngredients.prototype = Object.create(Window_Base.prototype);
Window_CraftingIngredients.prototype.constructor = Window_CraftingIngredients;
Window_CraftingIngredients.prototype.initialize = function (
x,
y,
width,
height
) {
Window_Base.prototype.initialize.call(this, x, y, width, height);
};
Window_CraftingIngredients.prototype.setItem = function (item) {
if (this._item !== item) {
this._item = item;
this.refresh();
}
};
Window_CraftingIngredients.prototype.refresh = function () {
this.contents.clear();
var x = 0;
var y = 0;
var lineHeight = this.lineHeight();
var width = this.contents.width - this.textPadding() * 2;
var existingCount = 0,
needed = 0;
this.changeTextColor(this.systemColor());
this.drawText(ingredientsText, x, y, width);
this.resetTextColor();
this._item._ingredients.forEach(function (ing) {
y += lineHeight;
needed = ing["amount"];
if (ing["item"] == currencyText) {
existingCount = $gameParty.gold();
this.drawText(ing["item"], x, y, width);
} else {
existingCount = $gameParty.numItems(ing["item"]);
this.drawItemName(ing["item"], x, y, width);
}
this.drawText("/" + needed, x, y, width, "right");
if (existingCount < needed) this.changeTextColor(this.crisisColor());
else this.changeTextColor(this.powerUpColor());
this.drawText(
existingCount,
x,
y,
width - this.textWidth("/" + needed),
"right"
);
this.resetTextColor();
}, this);
};
/*----------------------------------------------
* Window_CraftingAnimation
*---------------------------------------------*/
function Window_CraftingAnimation() {
this.initialize.apply(this, arguments);
}
Window_CraftingAnimation.prototype = Object.create(Window_Base.prototype);
Window_CraftingAnimation.prototype.constructor = Window_CraftingAnimation;
Window_CraftingAnimation.prototype.initialize = function (cat_id) {
Window_Base.prototype.initialize.call(
this,
0,
0,
Graphics.width,
Graphics.height
);
this._category = cat_id;
this._animation = $dataAnimations[animations[cat_id]];
this._finishedAnimation = false;
};
})();