From 5a8d6081f975536713974eccd0ed2371c8909495 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 23 Jan 2016 23:13:11 +0300 Subject: Add script function for find craft entry from db based on craft variable. New script command: findcraftentry CRAFTVAR, FLAG Where: CRAFTVAR - variable get from initcraft function. FLAG - flag related to npc. It allow search craft entries only with this flag. --- src/emap/craft.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/emap/craft.h | 3 + src/emap/craftconf.c | 1 + src/emap/craftconf.h | 2 + src/emap/init.c | 1 + src/emap/script.c | 12 ++- src/emap/script.h | 1 + 7 files changed, 262 insertions(+), 1 deletion(-) (limited to 'src/emap') 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 -- cgit v1.2.3-70-g09d2