summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emap/craft.c243
-rw-r--r--src/emap/craft.h3
-rw-r--r--src/emap/craftconf.c1
-rw-r--r--src/emap/craftconf.h2
-rw-r--r--src/emap/init.c1
-rw-r--r--src/emap/script.c12
-rw-r--r--src/emap/script.h1
7 files changed, 262 insertions, 1 deletions
diff --git a/src/emap/craft.c b/src/emap/craft.c
index e0164fe..ae36e6e 100644
--- a/src/emap/craft.c
+++ b/src/emap/craft.c
@@ -23,6 +23,7 @@
#include "ecommon/struct/strutildata.h"
#include "emap/craft.h"
+#include "emap/craftconf.h"
#include "emap/lang.h"
struct DBMap *craftvar_db = NULL;
@@ -351,3 +352,245 @@ bool craft_validate(TBL_PC *sd, const int id)
}
return true;
}
+
+static int find_inventory_item(TBL_PC *sd,
+ const int id,
+ const int amount)
+{
+ int i;
+ for (i = 0; i < MAX_INVENTORY; i++)
+ {
+ if (sd->status.inventory[i].nameid == id &&
+ sd->status.inventory[i].amount >= amount)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int find_inventory_equipped_item(TBL_PC *sd,
+ const int id)
+{
+ int i;
+ for (i = 0; i < MAX_INVENTORY; i++)
+ {
+ if (sd->status.inventory[i].nameid == id &&
+ sd->status.inventory[i].amount > 0 &&
+ sd->status.inventory[i].equip > 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static bool check_items_collection(TBL_PC *sd,
+ struct craft_items_collection *vector)
+{
+ int len = VECTOR_LENGTH(*vector);
+ int i;
+ if (len > 0)
+ {
+ for (i = 0; i < len; i ++)
+ {
+ struct item_pair *itemPair = &VECTOR_INDEX(*vector, i);
+ if (find_inventory_item(sd, itemPair->index, itemPair->amount) < 0)
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool check_equips(TBL_PC *sd,
+ struct craft_items_collection *vector)
+{
+ int len = VECTOR_LENGTH(*vector);
+ int i;
+ if (len > 0)
+ {
+ for (i = 0; i < len; i ++)
+ {
+ struct item_pair *itemPair = &VECTOR_INDEX(*vector, i);
+ if (find_inventory_equipped_item(sd, itemPair->index) < 0)
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool check_skills(TBL_PC *sd,
+ struct craft_items_collection *vector)
+{
+ int len = VECTOR_LENGTH(*vector);
+ int i;
+ if (len > 0)
+ {
+ for (i = 0; i < len; i ++)
+ {
+ struct item_pair *itemPair = &VECTOR_INDEX(*vector, i);
+ const int index = skill->get_index(itemPair->index);
+ if (!index)
+ return false;
+ if (sd->status.skill[index].lv < itemPair->amount)
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool check_quests(TBL_PC *sd,
+ struct craft_items_collection *vector)
+{
+ int len = VECTOR_LENGTH(*vector);
+ int i;
+ if (len > 0)
+ {
+ for (i = 0; i < len; i ++)
+ {
+ struct item_pair *itemPair = &VECTOR_INDEX(*vector, i);
+
+ int n;
+ ARR_FIND(0, sd->avail_quests, n, sd->quest_log[n].quest_id == itemPair->index);
+ if (n == sd->avail_quests)
+ return false;
+ if (sd->quest_log[n].count[0] < itemPair->amount)
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool check_inventories(TBL_PC *sd,
+ struct craft_db_entry *entry,
+ struct item_pair *inventory)
+{
+ int inv_count = VECTOR_LENGTH(entry->inventories);
+ bool correct = true;
+
+ int f;
+ for (f = 0; f < inv_count; f ++)
+ {
+ struct craft_db_inventory *entry_inventory = &VECTOR_INDEX(entry->inventories, f);
+ int i;
+ for (i = 0; i < craft_inventory_size; i ++)
+ {
+ struct item_pair *invItem = &inventory[i];
+ struct item_pair *entryItem = &entry_inventory->items[i];
+ if (invItem->index != entryItem->index ||
+ invItem->amount < entryItem->amount)
+ { // items not same or amount too small, skipping
+ correct = false;
+ continue;
+ }
+ }
+ if (correct)
+ return true;
+ correct = true;
+ }
+ return false;
+}
+
+static void simplify_craftvar(TBL_PC *sd,
+ struct item_pair *inventory,
+ struct craft_vardata *craft)
+{
+ int i;
+
+ // combine different slots from inventory var into one slot with id and amount
+ for (i = 0; i < craft_inventory_size; i ++)
+ {
+ struct item_pair *invPair = &inventory[i];
+ invPair->index = 0;
+ invPair->amount = 0;
+
+ struct craft_slot *slot = &craft->slots[i];
+ const int len = VECTOR_LENGTH(slot->items);
+ int f;
+ for (f = 0; f < len; f ++)
+ {
+ struct item_pair *pair = &VECTOR_INDEX(slot->items, f);
+ const int itemIndex = pair->index;
+ const int itemId = sd->status.inventory[itemIndex].nameid;
+ // additional check for craft var
+ if (invPair->index != 0 && invPair->index != itemId)
+ continue;
+ invPair->index = itemId;
+ invPair->amount += sd->status.inventory[itemIndex].amount;
+ }
+ }
+}
+
+static int craft_get_recipe(TBL_PC *sd,
+ struct craft_vardata *craft,
+ struct item_pair *inventory,
+ const int flag)
+{
+ if (!sd || !craft || !inventory)
+ return -1;
+
+ struct craft_db_entry *best_entry = NULL;
+ struct craft_db_entry *entry;
+
+ DBIterator* iter = db_iterator(craftconf_db);
+
+ for (entry = dbi_first(iter); dbi_exists(iter); entry = dbi_next(iter))
+ {
+ //ShowInfo("check recipes: %d\n", entry->id);
+ if ((flag && !(entry->flag & flag)) ||
+ sd->status.zeny < entry->price ||
+ sd->status.base_level < entry->level)
+ {
+ continue;
+ }
+ //ShowInfo("base correct\n");
+ if (!check_inventories(sd, entry, inventory))
+ continue;
+ //ShowInfo("inventories correct\n");
+ if (!check_items_collection(sd, &entry->delete_items))
+ continue;
+ //ShowInfo("delete_items correct\n");
+ if (!check_items_collection(sd, &entry->required_items))
+ continue;
+ //ShowInfo("required_items correct\n");
+ if (!check_equips(sd, &entry->required_equips))
+ continue;
+ //ShowInfo("required_equips correct\n");
+ if (!check_skills(sd, &entry->required_skills))
+ continue;
+ //ShowInfo("required_quests correct\n");
+ if (!check_quests(sd, &entry->required_quests))
+ continue;
+
+ //ShowInfo("found\n");
+ if (best_entry == NULL ||
+ entry->priority > best_entry->priority ||
+ entry->id < best_entry->id)
+ {
+ best_entry = entry;
+ }
+ }
+ dbi_destroy(iter);
+ return best_entry ? best_entry->id : -1;
+}
+
+int craft_find_entry(TBL_PC *sd,
+ const int craftvar,
+ const int flag)
+{
+ if (!sd)
+ return -1;
+
+ struct craft_vardata *craft = idb_get(craftvar_db, craftvar);
+ if (!craft)
+ {
+ ShowError("Craft object with id %d not exists.\n", craftvar);
+ return -1;
+ }
+
+ struct item_pair inventory[craft_inventory_size];
+ simplify_craftvar(sd, &inventory[0], craft);
+ const int recipe = craft_get_recipe(sd, craft, &inventory[0], flag);
+ //ShowInfo("found recipe: %d\n", recipe);
+ return recipe;
+}
diff --git a/src/emap/craft.h b/src/emap/craft.h
index a579c20..41ee694 100644
--- a/src/emap/craft.h
+++ b/src/emap/craft.h
@@ -12,6 +12,8 @@
extern struct DBMap *craftvar_db;
+VECTOR_STRUCT_DECL(craft_ids, int);
+
struct skill_pair
{
int id;
@@ -37,5 +39,6 @@ void craft_dump(TBL_PC *sd, const int id);
void craft_delete(const int id);
struct craft_slot *craft_get_slot(const int id, const int slot);
bool craft_validate(TBL_PC *sd, const int id);
+int craft_find_entry(TBL_PC *sd, const int craftvar, const int flag);
#endif // EVOL_MAP_CRAFT
diff --git a/src/emap/craftconf.c b/src/emap/craftconf.c
index 7705570..62f3230 100644
--- a/src/emap/craftconf.c
+++ b/src/emap/craftconf.c
@@ -272,6 +272,7 @@ static bool craft_read_db_sub(config_setting_t *craftt, int id, const char *sour
}
struct craft_db_entry *entry = craft_create_db_entry(class_);
+ entry->id = class_;
idb_put(craftconf_db, class_, entry);
safestrncpy(entry->name, str, sizeof(entry->name));
diff --git a/src/emap/craftconf.h b/src/emap/craftconf.h
index b9f4a73..b42c9d5 100644
--- a/src/emap/craftconf.h
+++ b/src/emap/craftconf.h
@@ -10,6 +10,8 @@
#include "emap/struct/itempair.h"
+extern struct DBMap *craftconf_db;
+
VECTOR_STRUCT_DECL(craft_items_collection, struct item_pair);
struct craft_db_inventory
diff --git a/src/emap/init.c b/src/emap/init.c
index ddff203..e628fb3 100644
--- a/src/emap/init.c
+++ b/src/emap/init.c
@@ -105,6 +105,7 @@ HPExport void plugin_init (void)
addScriptCommand("initcraft", "s", initCraft);
addScriptCommand("dumpcraft", "i", dumpCraft);
addScriptCommand("deletecraft", "i", deleteCraft);
+ addScriptCommand("findcraftentry", "ii", findCraftEntry);
addScriptCommand("getcraftslotid", "ii", getCraftSlotId);
addScriptCommand("getcraftslotamount", "ii", getCraftSlotAmount);
addScriptCommand("validatecraft", "i", validateCraft);
diff --git a/src/emap/script.c b/src/emap/script.c
index a7aac63..9d89fc7 100644
--- a/src/emap/script.c
+++ b/src/emap/script.c
@@ -532,7 +532,7 @@ BUILDIN(shop)
BUILDIN(getItemLink)
{
- struct item_data *i_data;
+ struct item_data *i_data = NULL;
char *item_name;
int item_id = 0;
@@ -1941,6 +1941,16 @@ BUILDIN(validateCraft)
return true;
}
+BUILDIN(findCraftEntry)
+{
+ getSDReturn(-1)
+ const int id = craft_find_entry(sd,
+ script_getnum(st, 2),
+ script_getnum(st, 3));
+ script_pushint(st, id);
+ return true;
+}
+
BUILDIN(getInvIndexLink)
{
getSDReturnS("")
diff --git a/src/emap/script.h b/src/emap/script.h
index 41164d2..bb40d54 100644
--- a/src/emap/script.h
+++ b/src/emap/script.h
@@ -73,5 +73,6 @@ BUILDIN(getCraftSlotAmount);
BUILDIN(validateCraft);
BUILDIN(getInvIndexLink);
BUILDIN(emotion);
+BUILDIN(findCraftEntry);
#endif // EVOL_MAP_SCRIPT