diff options
-rw-r--r-- | src/emap/craft.c | 344 | ||||
-rw-r--r-- | src/emap/craft.h | 38 | ||||
-rw-r--r-- | src/emap/init.c | 2 |
3 files changed, 379 insertions, 5 deletions
diff --git a/src/emap/craft.c b/src/emap/craft.c index 5e0abe3..4abd84d 100644 --- a/src/emap/craft.c +++ b/src/emap/craft.c @@ -10,11 +10,13 @@ #include "common/HPMi.h" #include "common/memmgr.h" #include "common/mmo.h" +#include "common/nullpo.h" #include "common/socket.h" #include "common/strlib.h" #include "map/itemdb.h" #include "map/npc.h" #include "map/pc.h" +#include "map/quest.h" #include "ecommon/utils/strutil.h" @@ -24,12 +26,320 @@ #include "emap/lang.h" struct DBMap *craftvar_db = NULL; +struct DBMap *craftconf_db = NULL; int craft_counter = 0; +struct craft_db_entry *craft_create_db_entry(const int id) +{ + struct craft_db_entry *entry = aCalloc(sizeof(struct craft_db_entry), 1); + if (!entry) + return NULL; + VECTOR_INIT(entry->inventories); + VECTOR_INIT(entry->create_items); + VECTOR_INIT(entry->delete_items); + VECTOR_INIT(entry->required_items); + VECTOR_INIT(entry->required_equips); + VECTOR_INIT(entry->required_skills); + VECTOR_INIT(entry->required_quests); + return entry; +} + +static bool craft_lookup_const(const config_setting_t *it, const char *name, int *value) +{ + if (libconfig->setting_lookup_int(it, name, value)) + { + return true; + } + else + { + const char *str = NULL; + if (libconfig->setting_lookup_string(it, name, &str)) + { + if (*str && script->get_constant(str, value)) + return true; + } + } + return false; +} + +static bool craft_get_const(const config_setting_t *it, int *value) +{ + const char *str = libconfig->setting_get_string(it); + if (str && *str && script->get_constant(str, value)) + return true; + + *value = libconfig->setting_get_int(it); + return true; +} + +static int craft_get_item_id(struct craft_db_entry *entry, + const char *const errorMessage, + const char *const name, + const char *const fieldName) +{ + if (!strcmp(name, "Empty")) + return 0; + + struct item_data* id = itemdb->search_name(name); + if (!id) + { + ShowWarning(errorMessage, entry->id, fieldName, name); + return 0; + } + return id->nameid; +} + +static void craft_read_source_inventory(struct craft_db_entry *entry, + config_setting_t *tt) +{ + int i32; + int i = 0; + if (!tt || !config_setting_is_group(tt)) + return; + + config_setting_t *item; + + int invLen = VECTOR_LENGTH(entry->inventories); + VECTOR_ENSURE(entry->inventories, invLen + 1, 1); + VECTOR_INSERTZEROED(entry->inventories, invLen); + struct craft_db_inventory *inventory = &VECTOR_INDEX(entry->inventories, invLen); + + while((item = libconfig->setting_get_elem(tt, i)) && i < craft_inventory_size) + { + int amount = 0; + const char *name = config_setting_name(item); + int itemId = craft_get_item_id(entry, "Wrong item name in craft %d in field %s in: %s\n", name, "SourceItems"); + if (!itemId) + { + inventory->items[i].index = 0; + inventory->items[i].amount = 0; + i ++; + continue; + } + if (craft_get_const(item, &i32) && i32 >= 0) + amount = i32; + + if (amount < 1) + { + inventory->items[i].index = 0; + inventory->items[i].amount = 0; + ShowWarning("Wrong item amount in craft %d in field SourceItems in: %d\n", entry->id, amount); + i ++; + continue; + } + + inventory->items[i].index = itemId; + inventory->items[i].amount = amount; + i ++; + } +} + +static void craft_read_items_collection(struct craft_db_entry *entry, + struct craft_items_collection *vector, + config_setting_t *t, + const char *const fieldName, + enum craft_field_type fieldType) +{ + int i32; + int i = 0; + if (!t) + return; + + config_setting_t *tt = libconfig->setting_get_member(t, fieldName); + + if (!tt || !config_setting_is_group(tt)) + return; + + config_setting_t *item; + + int len = 0; + while((item = libconfig->setting_get_elem(tt, i))) + { + int amount = 0; + const char *name = config_setting_name(item); + int itemId = 0; + if (fieldType == CRAFT_ITEM) + { + itemId = craft_get_item_id(entry, "Wrong item name in craft %d in field %s in: %s\n", name, fieldName); + if (!itemId) + { + i ++; + continue; + } + } + else if (fieldType == CRAFT_QUEST) + { + if (!script->get_constant(name, &itemId)) + { + ShowWarning("Wrong quest name in craft %d in field %s in: %s\n", entry->id, fieldName, name); + i ++; + continue; + } + if (!quest->db(itemId)) + { + ShowWarning("Wrong quest id in craft %d in field %s in: %s\n", entry->id, fieldName, name); + i ++; + continue; + } + } + else if (fieldType == CRAFT_SKILL) + { + itemId = skill->name2id(name); + if (!itemId) + { + ShowWarning("Wrong skill name in craft %d in field %s in: %s\n", entry->id, fieldName, name); + i ++; + continue; + } + } + else if (fieldType == CRAFT_BOOL) + { + itemId = craft_get_item_id(entry, "Wrong item name in craft %d in field %s in: %s\n", name, fieldName); + if (!itemId) + { + i ++; + continue; + } + } + + if (fieldType == CRAFT_BOOL) + { + if (!libconfig->setting_get_bool(item)) + { + i ++; + continue; + } + amount = 1; + } + else if (craft_get_const(item, &i32) && i32 >= 0) + { + amount = i32; + } + + if (amount < 1) + { + if (fieldType == CRAFT_ITEM) + { + ShowWarning("Wrong item amount in craft %d in field %s in: %d\n", entry->id, fieldName, amount); + } + else if (fieldType == CRAFT_QUEST) + { + ShowWarning("Wrong quest level in craft %d in field %s in: %d\n", entry->id, fieldName, amount); + } + else if (fieldType == CRAFT_SKILL) + { + ShowWarning("Wrong skill level in craft %d in field %s in: %d\n", entry->id, fieldName, amount); + } + i ++; + continue; + } + + VECTOR_ENSURE(*vector, len + 1, 1); + VECTOR_INSERTZEROED(*vector, len); + struct item_pair *pair = &VECTOR_INDEX(*vector, len); + len ++; + + pair->index = itemId; + pair->amount = amount; + //ShowInfo("%s: itemId=%d:%d\n", fieldName, itemId, amount); + i ++; + } +} + +#define readField(name, var, def) \ + if (craft_lookup_const(craftt, name, &i32) && i32 >= 0) \ + { \ + entry->var = i32; \ + } \ + else \ + { \ + entry->var = def; \ + } + +static bool craft_read_db_sub(config_setting_t *craftt, int id, const char *source) +{ + int class_; + int i32; + const char *str = NULL; + config_setting_t *t; + + if (!libconfig->setting_lookup_int(craftt, "Id", &class_)) + { + ShowWarning("craft_read_db_sub: Missing id in \"%s\", entry #%d, skipping.\n", source, class_); + return false; + } + if (!libconfig->setting_lookup_string(craftt, "Name", &str) || !*str) + { + ShowWarning("craft_read_db_sub: Missing Name in craft %d of \"%s\", skipping.\n", class_, source); + return false; + } + + struct craft_db_entry *entry = craft_create_db_entry(class_); + idb_put(craftconf_db, class_, entry); + + safestrncpy(entry->name, str, sizeof(entry->name)); + + //ShowInfo("Craft: id=%d, name=%s\n", class_, entry->name); + + readField("Priority", priority, 0); + readField("Price", price, 0); + readField("Lv", level, 0); + readField("Flag", flag, -1); + + if ((t = libconfig->setting_get_member(craftt, "SourceItems")) && config_setting_is_list(t)) + { + int i, len = libconfig->setting_length(t); + + for (i = 0; i < len; i++) + { + craft_read_source_inventory(entry, libconfig->setting_get_elem(t, i)); + } + } + + craft_read_items_collection(entry, &entry->create_items, craftt, "CreateItems", CRAFT_ITEM); + craft_read_items_collection(entry, &entry->delete_items, craftt, "DeleteItems", CRAFT_ITEM); + craft_read_items_collection(entry, &entry->required_items, craftt, "RequiredItems", CRAFT_ITEM); + craft_read_items_collection(entry, &entry->required_skills, craftt, "RequiredSkills", CRAFT_ITEM); + craft_read_items_collection(entry, &entry->required_quests, craftt, "RequiredQuests", CRAFT_QUEST); + craft_read_items_collection(entry, &entry->required_equips, craftt, "RequiredEquips", CRAFT_BOOL); + + return true; +} +#undef readField + +static void load_craft_db(const char *filename) +{ + config_t craft_db_conf; + char filepath[256]; + config_setting_t *cdb; + config_setting_t *t; + int i = 0; + + nullpo_retv(filename); + sprintf(filepath, "%s/%s", map->db_path, filename); + + if (libconfig->read_file(&craft_db_conf, filepath) || + !(cdb = libconfig->setting_get_member(craft_db_conf.root, "craft_db"))) + { + ShowError("can't read %s\n", filepath); + return; + } + + while ((t = libconfig->setting_get_elem(cdb, i++))) + { + craft_read_db_sub(t, i - 1, filepath); + } + libconfig->destroy(&craft_db_conf); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, filepath); + +} + void do_init_craft(void) { craftvar_db = idb_alloc(DB_OPT_RELEASE_BOTH); + craftconf_db = idb_alloc(DB_OPT_RELEASE_BOTH); + load_craft_db("craft_db.conf"); } static void delete_craft_var(struct craft_vardata *craft) @@ -44,9 +354,22 @@ static void delete_craft_var(struct craft_vardata *craft) } } -static int delete_craft_sub(DBKey key __attribute__ ((unused)), - DBData *data, - va_list args __attribute__ ((unused))) +static void delete_craft_entry(struct craft_db_entry *entry) +{ + if (!entry) + return; + VECTOR_CLEAR(entry->inventories); + VECTOR_CLEAR(entry->create_items); + VECTOR_CLEAR(entry->delete_items); + VECTOR_CLEAR(entry->required_items); + VECTOR_CLEAR(entry->required_equips); + VECTOR_CLEAR(entry->required_skills); + VECTOR_CLEAR(entry->required_quests); +} + +static int delete_craftvar_sub(DBKey key __attribute__ ((unused)), + DBData *data, + va_list args __attribute__ ((unused))) { struct craft_vardata *craft = DB->data2ptr(data); if (!craft) @@ -56,9 +379,22 @@ static int delete_craft_sub(DBKey key __attribute__ ((unused)), return 0; } +static int delete_craftconf_sub(DBKey key __attribute__ ((unused)), + DBData *data, + va_list args __attribute__ ((unused))) +{ + struct craft_db_entry *craft = DB->data2ptr(data); + if (!craft) + return 0; + + delete_craft_entry(craft); + return 0; +} + void do_final_craft(void) { - craftvar_db->destroy(craftvar_db, delete_craft_sub); + craftvar_db->destroy(craftvar_db, delete_craftvar_sub); + craftconf_db->destroy(craftconf_db, delete_craftconf_sub); } bool craft_checkstr(TBL_PC *sd, const char *craftstr) diff --git a/src/emap/craft.h b/src/emap/craft.h index 6d92bad..47fea8f 100644 --- a/src/emap/craft.h +++ b/src/emap/craft.h @@ -16,6 +16,12 @@ struct item_pair int amount; }; +struct skill_pair +{ + int id; + int level; +}; + struct craft_slot { VECTOR_DECL(struct item_pair) items; @@ -26,6 +32,38 @@ struct craft_vardata struct craft_slot slots[craft_inventory_size]; }; +struct craft_db_inventory +{ + struct item_pair items[craft_inventory_size]; +}; + +VECTOR_STRUCT_DECL(craft_items_collection, struct item_pair); + +struct craft_db_entry +{ + int id; + char name[32]; + VECTOR_DECL(struct craft_db_inventory) inventories; + struct craft_items_collection create_items; + struct craft_items_collection delete_items; + struct craft_items_collection required_items; + struct craft_items_collection required_equips; + struct craft_items_collection required_skills; + struct craft_items_collection required_quests; + int priority; + int price; + int level; + int flag; +}; + +enum craft_field_type +{ + CRAFT_ITEM, + CRAFT_QUEST, + CRAFT_SKILL, + CRAFT_BOOL +}; + void do_init_craft(void); void do_final_craft(void); bool craft_checkstr(TBL_PC *sd, const char *craftstr); diff --git a/src/emap/init.c b/src/emap/init.c index f9070b1..5378597 100644 --- a/src/emap/init.c +++ b/src/emap/init.c @@ -147,7 +147,6 @@ HPExport void plugin_init (void) addScriptCommand("emotion", "i??", emotion); do_init_langs(); - do_init_craft(); addPacket(0x7530, 22, map_parse_version, hpClif_Parse); addPacket(0xb07, 26, map_parse_join_channel, hpClif_Parse); @@ -273,6 +272,7 @@ HPExport void server_preinit (void) HPExport void server_online (void) { + do_init_craft(); } HPExport void plugin_final (void) |