summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesusaves <cpntb1@ymail.com>2020-07-10 16:32:39 +0000
committerJesusaves <cpntb1@ymail.com>2020-07-10 16:32:39 +0000
commit055ae0a6bb07db30f81236b34ae9ecea56249bbe (patch)
tree2c2927704c9b8cd6c0e01fa661e6f590f373c317
parentb2d6cf5a3c1a1547d1017e45a37e6492639b7f00 (diff)
downloadserverdata-055ae0a6bb07db30f81236b34ae9ecea56249bbe.tar.gz
serverdata-055ae0a6bb07db30f81236b34ae9ecea56249bbe.tar.bz2
serverdata-055ae0a6bb07db30f81236b34ae9ecea56249bbe.tar.xz
serverdata-055ae0a6bb07db30f81236b34ae9ecea56249bbe.zip
Implements Crafting Core system
Recipes etc. not included
-rw-r--r--db/constants.conf13
-rw-r--r--db/craft_db.conf27
-rw-r--r--db/re/skill_db.conf9
-rw-r--r--db/re/skill_tree.conf5
-rw-r--r--npc/008-2-16/stove.txt8
-rw-r--r--npc/008-2-16/yannika.txt13
-rw-r--r--npc/012-2-5/toichi.txt60
-rw-r--r--npc/functions/crafting.txt94
-rw-r--r--npc/functions/main.txt19
-rw-r--r--npc/functions/quest-debug/055-General_Cooking.txt14
-rw-r--r--npc/items/recipes.txt208
-rw-r--r--npc/scripts.conf1
12 files changed, 413 insertions, 58 deletions
diff --git a/db/constants.conf b/db/constants.conf
index 59dce74b..2c0fb424 100644
--- a/db/constants.conf
+++ b/db/constants.conf
@@ -4187,7 +4187,18 @@ constants_db: {
RUSTYPICK_INN: 2
comment__: "CRAFT enum"
- CRAFT_SANDWICH: 4
+ CRAFT_COOKING: 4
+ CRAFT_ALCHEMY: 8
+ CRAFT_SMITHERY: 16
+ CRAFT_TAILORING: 32
+ CRAFT_JEWELERY: 64
+
+ comment__: "CRAFT Rarity enum"
+ CRAFT_BASIC: 1
+ CRAFT_INTERMEDIARY: 2
+ CRAFT_ADVANCED: 4
+ CRAFT_EXPERT: 8
+ CRAFT_MASTER: 16
comment__: "Being actions"
ACTION_STAND: 0
diff --git a/db/craft_db.conf b/db/craft_db.conf
index 2c338390..b8cdfc56 100644
--- a/db/craft_db.conf
+++ b/db/craft_db.conf
@@ -391,4 +391,31 @@ craft_db: (
}
Priority: 10
},
+// Example recipe, incl for testing, do not use on live
+{
+ Id: 8
+ Name: "CraftInfantryHelmet"
+ Flag: 16
+ ReturnCode: 2906
+ // InfantryHelmet
+ SourceItems:
+ (
+ {
+ IronOre: 12
+ Coal: 3
+ Moss: 2
+ Dagger: 1
+ },
+ )
+ CreateItems:
+ (
+ {
+ PileOfAsh: 1
+ },
+ )
+ RequiredItems: {
+ RecipeBook: 1
+ }
+ Priority: 10
+},
)
diff --git a/db/re/skill_db.conf b/db/re/skill_db.conf
index 30cc7466..6749fcd3 100644
--- a/db/re/skill_db.conf
+++ b/db/re/skill_db.conf
@@ -38652,4 +38652,13 @@ skill_db: (
}
CoolDown: 3000
},
+{
+ Id: 20004
+ Name: "EVOL_CRAFTING"
+ Description: "Crafting"
+ MaxLevel: 10
+ SkillType: {
+ Passive: true
+ }
+},
)
diff --git a/db/re/skill_tree.conf b/db/re/skill_tree.conf
index 20a4dd64..95fc3daa 100644
--- a/db/re/skill_tree.conf
+++ b/db/re/skill_tree.conf
@@ -27,6 +27,7 @@ Job_Name: { // Job names as in src/map/pc.c (they are hardcoded at the moment so
Viro: {
skills: {
+ EVOL_CRAFTING: 0
SM_SWORD: 0
SM_TWOHAND: 0
AC_OWL: 0
@@ -91,6 +92,7 @@ Viro: {
CaveUkar: {
skills: {
+ EVOL_CRAFTING: 0
SM_SWORD: 0
SM_TWOHAND: 0
AC_OWL: 0
@@ -155,6 +157,7 @@ CaveUkar: {
FireKralog: {
skills: {
+ EVOL_CRAFTING: 0
SM_SWORD: 0
SM_TWOHAND: 0
AC_OWL: 0
@@ -219,6 +222,7 @@ FireKralog: {
LightRaijin: {
skills: {
+ EVOL_CRAFTING: 0
SM_SWORD: 0
SM_TWOHAND: 0
AC_OWL: 0
@@ -283,6 +287,7 @@ LightRaijin: {
SeaTritan: {
skills: {
+ EVOL_CRAFTING: 0
SM_SWORD: 0
SM_TWOHAND: 0
AC_OWL: 0
diff --git a/npc/008-2-16/stove.txt b/npc/008-2-16/stove.txt
index 91036c44..40dfeca9 100644
--- a/npc/008-2-16/stove.txt
+++ b/npc/008-2-16/stove.txt
@@ -25,14 +25,14 @@
setskin "craft4";
.@var$ = requestcraft(4); // Limit: 4 items
.@craft = initcraft(.@var$);
- .@entry = findcraftentry(.@craft, CRAFT_SANDWICH);
+ .@entry = findcraftentry(.@craft, CRAFT_COOKING);
setskin "";
// Does the recipe exist and is a sandwich?
if (.@entry < 0)
{
narrator
- l("You don't know how to make a sandwich with that."),
+ l("You don't know how any recipe with that."),
l("Do you want to try again?");
if (askyesno() == ASK_YES)
.@tryAgain=true;
@@ -52,7 +52,7 @@
{
// Even if the recipe is right, if you don't have it on your
// recipe book, it should be deemed invalid.
- if (COOKING_RECIPES[.@entry])
+ if (RECIPES[.@entry])
{
usecraft .@craft;
narrator
@@ -62,7 +62,7 @@
else
{
narrator
- l("You don't know how to make a sandwich with that."),
+ l("You don't know how any recipe with that."),
l("Do you want to try again?");
}
diff --git a/npc/008-2-16/yannika.txt b/npc/008-2-16/yannika.txt
index 7223b70c..9599a5d9 100644
--- a/npc/008-2-16/yannika.txt
+++ b/npc/008-2-16/yannika.txt
@@ -10,7 +10,7 @@
// 0: Doesn't knows the quest
// 1: Received the quest for the Cookbook
// 2: Completed the quest for the Cookbook
-// COOKING_RECIPES
+// RECIPES
// Controls which recipes you know and doesn't.
// It is an array with Craft Constants.
@@ -101,7 +101,7 @@
}
delitem .@item1, .@ammo1;
delitem .@item2, .@ammo2;
- COOKING_RECIPES[.@craft]=true;
+ RECIPES[.@craft]=true;
speech
l("This is how you do it! HAAH!");
next;
@@ -112,6 +112,7 @@
}
// Yannika can make sandwiches for players
+ // FIXME: Actually, Yannika will cook anything for players >__>
function sudo_make_sandwich
{
speech
@@ -128,7 +129,7 @@
setskin "craft4";
.@var$ = requestcraft(4); // Limit: 4 items
.@craft = initcraft(.@var$);
- .@entry = findcraftentry(.@craft, CRAFT_SANDWICH);
+ .@entry = findcraftentry(.@craft, CRAFT_COOKING);
setskin "";
// Does the recipe exist and is a sandwich?
@@ -211,7 +212,7 @@
{
case CommonCarp:
case GrassCarp:
- if (COOKING_RECIPES[CraftCarpSandwich])
+ if (RECIPES[CraftCarpSandwich])
{
speech
lg("Haha, silly you! You already know the recipe! Read the @@ if you forgot!", getitemlink(RecipeBook));
@@ -223,7 +224,7 @@
break;
case Manana:
- if (COOKING_RECIPES[CraftMananaSandwich])
+ if (RECIPES[CraftMananaSandwich])
{
speech
lg("Haha, silly you! You already know the recipe! Read the @@ if you forgot!", getitemlink(RecipeBook));
@@ -235,7 +236,7 @@
break;
case PiouLegs:
- if (COOKING_RECIPES[CraftPioulegSandwich])
+ if (RECIPES[CraftPioulegSandwich])
{
speech
lg("Haha, silly you! You already know the recipe! Read the @@ if you forgot!", getitemlink(RecipeBook));
diff --git a/npc/012-2-5/toichi.txt b/npc/012-2-5/toichi.txt
index e1759e04..c2ff6c78 100644
--- a/npc/012-2-5/toichi.txt
+++ b/npc/012-2-5/toichi.txt
@@ -6,17 +6,69 @@
// THIS IS A PLACEHOLDER!
012-2-5,40,35,0 script Toichi NPC_TOICHI,{
+ function askCrafting;
speech
l("Hi there."),
l("My name is Toichi, and it seems I am the only one working on this lazy island.");
- next;
- mesq l("So I kindly request you not to listen to that stupid Rosen, saying 'Toichi is lazy'.");
- next;
- mesq l("At least I am doing something!");
+ next;
+ mesq l("So I kindly request you not to listen to that stupid Rosen, saying 'Toichi is lazy'.");
+ next;
+ mesq l("At least I am doing something!");
+ // TODO: Add here a check for crafting skills
+ askCrafting();
close;
+function askCrafting {
+ next;
+ select
+ l("Okay..."),
+ l("Hey, do you mind if I use your equipment?"),
+ rif(is_dev(), "[Debug]");
+ mes "";
+ if (@menu == 1)
+ return;
+
+ // Debug
+ if (debug && @menu == 3)
+ RECIPES[CraftInfantryHelmet]=!RECIPES[CraftInfantryHelmet];
+ if (debug || @menu == 3)
+ mesf("[DEBUG] Knows the infantry helmet recipe? %s",
+ (RECIPES[CraftInfantryHelmet] ? "YES" : "NO"));
+
+ mesn;
+ mesq l("Sure, go ahead. But I'll charge you %d E per craft as commission!", .price);
+ next;
+ do {
+ mesc l("What will you craft today?");
+ mesc l("It costs %d E to use.", .price), 1;
+ if (Zeny < .price)
+ close;
+
+ if (SmithSystem()) {
+ // This should NEVER, EVER happen.
+ if (Zeny < .price) {
+ mesc l("WARNING, you have been detected cheating and thus, violating Gasaron Anti-Theft Policy."), 1;
+ mesc l("You were jailed and now need a GM to get you out of there."), 1;
+ // At this point I just c/p the code
+ logmes "WARNING, "+strcharinfo(0)+" found out cheating, only had "+Zeny+" Esperins for craft table. Jailed.", LOGMES_ATCOMMAND;
+ atcommand("@jail "+strcharinfo(0));
+ Zeny=0;
+ close;
+ }
+ Zeny-=.price;
+ mesc l("Success!"), 3;
+ } else {
+ mesc l("That didn't work!"), 1;
+ }
+ next;
+ mesc l("Try again?");
+ } while (askyesno() == ASK_YES);
+ return;
+}
+
OnInit:
.sex = G_MALE;
.distance = 4;
+ .price = 6000;
end;
}
diff --git a/npc/functions/crafting.txt b/npc/functions/crafting.txt
new file mode 100644
index 00000000..ba032f41
--- /dev/null
+++ b/npc/functions/crafting.txt
@@ -0,0 +1,94 @@
+// Moubootaur Legends Script
+// Author:
+// Jesusalva
+// Description:
+// Smith System (Unified)
+// Notes:
+// Modified for The Mana World: rEvolt
+//
+// This one is more crazy. Cannot be equipping target craft.
+// After successful craft, we use CraftDB return code to equip() the
+// new item and apply a random option bonus based on crafter skills
+// eg. setequipoption(EQI_HAND_R, 1, VAR_STRAMOUNT, 5)
+
+// Usage: SmithSystem ({scope=CRAFT_SMITHERY, checks=True})
+// Returns true on success, false on failure
+function script SmithSystem {
+ .@scope=getarg(0, CRAFT_SMITHERY);
+ mesc l("WARNING: Strange bugs may happen if you attempt to craft an item you already have on inventory!"), 1;
+ setskin "craft4";
+ .@var$ = requestcraft(4);
+ .@craft = initcraft(.@var$);
+ .@entry = findcraftentry(.@craft, .@scope);
+ if (debug || $@GM_OVERRIDE) mes "found craft entry: " + .@entry;
+ if (debug || $@GM_OVERRIDE) mes "knowledge value: " + .knowledge[.@entry];
+ if (.@entry < 0) {
+ .success=false;
+ } else {
+ if (!getarg(1, true) || RECIPES[.@entry]) {
+ // Player craft item and setup base variables
+ usecraft .@craft;
+ .@it=getcraftcode(.@entry);
+ .@lv=getiteminfo(.@it, ITEMINFO_ELV);
+ .@skill=getskilllv(EVOL_CRAFTING);
+
+ // Update your CRAFTING_SCORE
+ CRAFTING_SCORE+=.@lv;
+
+ // Obtain the item. No bounds or restrictions applied.
+ getitem(.@it, 1);
+
+ // This is where we add options - this is oversimplified
+ // delinventorylist() is needed, because we'll rely on rfind()
+ delinventorylist();
+ getinventorylist();
+ .@index=array_rfind(@inventorylist_id, .@it);
+
+ // Prepare the options
+ .@isweapon=(getiteminfo(.@it, ITEMINFO_TYPE) == IT_WEAPON);
+ .@bonus=(.@isweapon ? VAR_ATTPOWER : VAR_ITEMDEFPOWER);
+ .@magic=(.@isweapon ? VAR_ATTMPOWER : VAR_MDEFPOWER);
+ .@buffs=(.@isweapon ? VAR_HITSUCCESSVALUE : VAR_AVOIDSUCCESSVALUE);
+ .@heals=(.@isweapon ? VAR_MAXSPAMOUNT : VAR_MAXHPAMOUNT);
+
+ // Now we need to randomly decide what will be .@opt1 and .@opt2
+ // Would be better to not rely on rand here, though.
+ .@opt1=any(.@bonus, .@magic);
+ .@opt2=any(.@buffs, .@heals);
+
+ // Apply the bonuses. They're capped by equip level and based on:
+ // Equip level, crafting experience and crafting skill
+ .@val=min(.@lv, (.@skill*CRAFTING_SCORE)/100+.@skill);
+
+ // MDEF rule range is 99 while DEF rule range is 399
+ // This is a really hackish way, for the record
+ if (.@opt1 == VAR_MDEFPOWER)
+ .@val=.@val/4;
+
+ // First option will always succeed
+ .@val1=rand2(.@val);
+ setitemoptionbyindex(.@index, 0, .@opt1, .@val1);
+
+ // Lucky roll (5% per skill level, capped at 50%)
+ // The lucky roll will add the extra attributes
+ if (rand2(20) < .@skill) {
+ .@val2=rand2(.@val);
+ setitemoptionbyindex(.@index, 1, .@opt2, .@val2);
+ }
+
+ // Get experience for the craft
+ // I'm using the same EXP formula from Moubootaur Legends
+ // Which is based on the item sell price
+ .@xp=getiteminfo(.@it, ITEMINFO_SELLPRICE);
+ getexp .@xp+BaseLevel, (.@xp/3)+BaseLevel+JobLevel;
+ .success=true;
+ } else {
+ .success=false;
+ }
+ }
+ deletecraft .@craft;
+ setskin "";
+ return .success;
+}
+
+
diff --git a/npc/functions/main.txt b/npc/functions/main.txt
index 9618e47e..e4c4cd88 100644
--- a/npc/functions/main.txt
+++ b/npc/functions/main.txt
@@ -269,3 +269,22 @@ function script get_race {
return .@allskins$[.@g] + " " + .@allraces$[.@g];
}
+// Clear output of getinventorylist()
+// delinventorylist()
+function script delinventorylist {
+ deletearray @inventorylist_id;
+ deletearray @inventorylist_amount;
+ deletearray @inventorylist_equip;
+ deletearray @inventorylist_refine;
+ deletearray @inventorylist_identify;
+ deletearray @inventorylist_attribute;
+ deletearray @inventorylist_card1;
+ deletearray @inventorylist_card2;
+ deletearray @inventorylist_card3;
+ deletearray @inventorylist_card4;
+ deletearray @inventorylist_expire;
+ deletearray @inventorylist_bound;
+ @inventorylist_count=0;
+ return;
+}
+
diff --git a/npc/functions/quest-debug/055-General_Cooking.txt b/npc/functions/quest-debug/055-General_Cooking.txt
index ed9fb685..76e23b17 100644
--- a/npc/functions/quest-debug/055-General_Cooking.txt
+++ b/npc/functions/quest-debug/055-General_Cooking.txt
@@ -10,7 +10,7 @@ function script QuestDebug55 {
mes "General_Cooking";
mes "---";
mes l("Quest state: @@", getq(General_Cooking));
- mes l("Known Recipes: @@", array_entries(COOKING_RECIPES));
+ mes l("Known Recipes: @@", array_entries(RECIPES));
next;
select
@@ -33,14 +33,14 @@ function script QuestDebug55 {
getitem RecipeBook, 1;
break;
case 5:
- COOKING_RECIPES[CraftCarpSandwich]=true;
- COOKING_RECIPES[CraftMananaSandwich]=true;
- COOKING_RECIPES[CraftPioulegSandwich]=true;
+ RECIPES[CraftCarpSandwich]=true;
+ RECIPES[CraftMananaSandwich]=true;
+ RECIPES[CraftPioulegSandwich]=true;
break;
case 6:
- COOKING_RECIPES[CraftCarpSandwich]=false;
- COOKING_RECIPES[CraftMananaSandwich]=false;
- COOKING_RECIPES[CraftPioulegSandwich]=false;
+ RECIPES[CraftCarpSandwich]=false;
+ RECIPES[CraftMananaSandwich]=false;
+ RECIPES[CraftPioulegSandwich]=false;
break;
}
diff --git a/npc/items/recipes.txt b/npc/items/recipes.txt
index 3fb3309c..485336e3 100644
--- a/npc/items/recipes.txt
+++ b/npc/items/recipes.txt
@@ -5,50 +5,114 @@
// Description:
// Contains recipe books for Evol Online
-- script #RecipeBook NPC_HIDDEN,{
+// showRecipe( Craft, Bonus, {amount 1, item 1}, {amount 2, item 2}... )
+function script showRecipe {
+ if (getargcount() < 3 || getargcount() % 2 != 0)
+ return false;//Exception("Faulty recipe skill command invoked - error");
- function read_book {
-
- setnpcdialogtitle l(.book_name$);
-
- mesc l("Eating is a necessity, but cooking is an art.");
- mesc l("(All items must be placed exactly in this order for cooking work.)");
- next;
- mesc l("List of known cooking recipes:");
- mes "";
- mes ".:: " + l("Sandwiches") + " ::.";
- mes "";
- if (COOKING_RECIPES[CraftCarpSandwich]) {
- mes l("@@", getitemlink(CarpSandwich));
- mesc l("* @@ @@", 1, getitemlink(Bread));
- mesc l("* @@ @@", 3, getitemlink(LettuceLeaf));
- mesc l("* @@ @@", 2, getitemlink(Cheese));
- mesc l("* @@ @@", 1, getitemlink(CommonCarp));
- mes "";
- }
- if (COOKING_RECIPES[CraftPioulegSandwich]) {
- mes l("@@", getitemlink(PioulegSandwich));
- mesc l("* @@ @@", 1, getitemlink(Bread));
- mesc l("* @@ @@", 3, getitemlink(LettuceLeaf));
- mesc l("* @@ @@", 2, getitemlink(Cheese));
- mesc l("* @@ @@", 1, getitemlink(PiouLegs));
- mes "";
- }
- if (COOKING_RECIPES[CraftMananaSandwich]) {
- mes l("@@", getitemlink(MananaSandwich));
- mesc l("* @@ @@", 1, getitemlink(Bread));
- mesc l("* @@ @@", 3, getitemlink(LettuceLeaf));
- mesc l("* @@ @@", 2, getitemlink(Cheese));
- mesc l("* @@ @@", 1, getitemlink(Manana));
+ if (RECIPES[getarg(0)]) {
+ if (getarg(1)) {
+ mes l(".:: %s Recipe ::.", getitemlink(getarg(1)));
+
+ for (.@i=2;.@i < getargcount(); .@i++) {
+ mesc l("%d/%d %s", countitem(getarg(.@i+1)), getarg(.@i), getitemlink(getarg(.@i+1)));
+ .@i++;
+ }
mes "";
}
+ return true;
+ }
+ return false;
+}
+
+- script #RecipeBook NPC_HIDDEN,{
+ function read_book;
+ function read_cooking;
+ function read_smithery;
+ end;
- close;
+function read_book {
+ setnpcdialogtitle l(.book_name$);
+ mesc l("This book has several bookmarks. Which one will you open?");
+ next;
+ menuint
+ l("Cooking"), CRAFT_COOKING,
+ l("Alchemy"), CRAFT_ALCHEMY,
+ l("Smithery"), CRAFT_SMITHERY,
+ l("Tailoring"), CRAFT_TAILORING,
+ l("Jewelery"), CRAFT_JEWELERY;
+ mes "";
+ switch (@menuret) {
+ case CRAFT_COOKING:
+ read_cooking(); break;
+ case CRAFT_SMITHERY:
+ read_smithery(); break;
+ default:
+ mesc l("Unfortunately, there is nothing on this bookmark.");
+ mesc l("Perhaps, in future, someone adds it to this world.");
+ break;
}
+ next;
+ return;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+function read_cooking {
+
+ setnpcdialogtitle l("Cooking Recipes");
+
+ mesc l("Eating is a necessity, but cooking is an art.");
+ mesc l("(All items must be placed exactly in this order for cooking work.)");
+ next;
+ mesc l("List of known cooking recipes:");
+ mes "";
+ mes ".:: " + l("Sandwiches") + " ::.";
+ mes "";
+ showRecipe(CraftCarpSandwich, CarpSandwich,
+ 1, Bread,
+ 3, LettuceLeaf,
+ 2, Cheese,
+ 1, CommonCarp);
+ showRecipe(CraftPioulegSandwich, PioulegSandwich,
+ 1, Bread,
+ 3, LettuceLeaf,
+ 2, Cheese,
+ 1, PiouLegs);
+ showRecipe(CraftMananaSandwich, MananaSandwich,
+ 1, Bread,
+ 3, LettuceLeaf,
+ 2, Cheese,
+ 1, Manana);
+
+ return;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+function read_smithery {
+
+ setnpcdialogtitle l("Smithery Recipes");
+
+ mesc l("You will trust your life to this, so you better do a good job!");
+ mesc l("(All items must be placed exactly in this order.)");
+ next;
+ mesc l("List of known smithery recipes:");
+
+ mes "";
+ mes ".:: " + l("Helmets") + " ::.";
+ mes "";
+ showRecipe(CraftInfantryHelmet, InfantryHelmet,
+ 12, IronOre,
+ 3, Coal,
+ 2, Moss,
+ 1, Dagger);
+
+ return;
+}
+
OnUse:
if (openbook())
- read_book;
+ read_book();
closeclientdialog();
close;
@@ -58,3 +122,75 @@ OnInit:
.distance = 1;
end;
}
+
+//////////////////////////////////////////////////////
+// Below this line are utils for Gacha. We use callfunc() on itemDB.
+// Types: see constants.db - everything is a bitwise here
+// Rarity: 1 - basic, 2 - intermediary, 4 - advanced, 8 - expert, 16 - master
+// Rarity: 1 - training, 2 - basic, 4 - advanced, 8 - expert, 16 - legendary
+// Keep in mind! Expert and Master blueprints must be restricted!
+// MakeBlueprint(type, rarity)
+function script MakeBlueprint {
+ .@type=getarg(0, -1);
+ .@rarity=getarg(1, 1);
+
+ if (.@type & CRAFT_COOKING) {
+
+ // ----------------------------------
+ if (.@rarity & CRAFT_BASIC) {
+ }
+ if (.@rarity & CRAFT_INTERMEDIARY) {
+ }
+ if (.@rarity & CRAFT_ADVANCED) {
+ }
+ if (.@rarity & CRAFT_EXPERT) {
+ }
+ if (.@rarity & CRAFT_MASTER) {
+ }
+ // ----------------------------------
+
+ }
+ else if (.@type & CRAFT_SMITHERY)
+ {
+
+ // ----------------------------------
+ if (.@rarity & CRAFT_BASIC) {
+ }
+ if (.@rarity & CRAFT_INTERMEDIARY) {
+ array_push(.@recipes, CraftInfantryHelmet);
+ }
+ if (.@rarity & CRAFT_ADVANCED) {
+ }
+ if (.@rarity & CRAFT_EXPERT) {
+ }
+ if (.@rarity & CRAFT_MASTER) {
+ }
+ // ----------------------------------
+
+ }
+
+ // We don't have a .@recipes array D:
+ if (array_entries(.@recipes) <= 0) {
+ dispbottom l("This blueprint was blank.");
+ return;
+ }
+
+ // Select a recipe randomly
+ .@rcp=any_of(.@recipes);
+
+ // Double precision failsafe
+ if (RECIPES[.@rcp])
+ .@rcp=any_of(.@recipes);
+
+ // Learn the recipe or lose the item (and gain some EXP)
+ if (RECIPES_[.@rcp]) {
+ dispbottom l("It was a recipe you already knew...");
+ getexp (BaseLevel+JobLevel)*rand2(1,.@rarity), JobLevel+rand2(1,.@rarity);
+ } else {
+ dispbottom l("Learned a new recipe!");
+ RECIPES[.@rcp]=true;
+ }
+ return;
+}
+
+
diff --git a/npc/scripts.conf b/npc/scripts.conf
index 4ad30e0e..4e144bf6 100644
--- a/npc/scripts.conf
+++ b/npc/scripts.conf
@@ -56,6 +56,7 @@
"npc/functions/manhole.txt",
"npc/functions/skills.txt",
"npc/functions/lockpicks.txt",
+"npc/functions/crafting.txt",
// quest debug
"npc/functions/quest-debug/functions.txt",