diff options
Diffstat (limited to 'src/map/npc.c')
-rw-r--r-- | src/map/npc.c | 158 |
1 files changed, 135 insertions, 23 deletions
diff --git a/src/map/npc.c b/src/map/npc.c index 7f003c321..7e1dab1b2 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1585,11 +1585,11 @@ static void npc_market_fromsql(void) if( !(nd = npc->name2id(name)) ) { ShowError("npc_market_fromsql: NPC '%s' not found! skipping...\n",name); - npc->market_delfromsql_sub(name, USHRT_MAX); + npc->market_delfromsql_sub(name, INT_MAX); continue; } else if (nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_MARKET) { ShowError("npc_market_fromsql: NPC '%s' is not proper for market, skipping...\n",name); - npc->market_delfromsql_sub(name, USHRT_MAX); + npc->market_delfromsql_sub(name, INT_MAX); continue; } @@ -1611,10 +1611,10 @@ static void npc_market_fromsql(void) /** * Saves persistent NPC Market Data into SQL **/ -static void npc_market_tosql(struct npc_data *nd, unsigned short index) +static void npc_market_tosql(struct npc_data *nd, int index) { nullpo_retv(nd); - Assert_retv(index < nd->u.scr.shop->items); + Assert_retv(index >= 0 && index < nd->u.scr.shop->items); if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%u')", map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty)) Sql_ShowDebug(map->mysql_handle); @@ -1622,9 +1622,9 @@ static void npc_market_tosql(struct npc_data *nd, unsigned short index) /** * Removes persistent NPC Market Data from SQL */ -static void npc_market_delfromsql_sub(const char *npcname, unsigned short index) +static void npc_market_delfromsql_sub(const char *npcname, int index) { - if( index == USHRT_MAX ) { + if (index == INT_MAX ) { if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_market_data_db, npcname) ) Sql_ShowDebug(map->mysql_handle); } else { @@ -1636,12 +1636,115 @@ static void npc_market_delfromsql_sub(const char *npcname, unsigned short index) /** * Removes persistent NPC Market Data from SQL **/ -static void npc_market_delfromsql(struct npc_data *nd, unsigned short index) +static void npc_market_delfromsql(struct npc_data *nd, int index) { nullpo_retv(nd); - Assert_retv(index == USHRT_MAX || index < nd->u.scr.shop->items); - npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid); + Assert_retv(index == INT_MAX || (index >= 0 && index < nd->u.scr.shop->items)); + npc->market_delfromsql_sub(nd->exname, index == INT_MAX ? index : nd->u.scr.shop->item[index].nameid); } + +/** + * Loads persistent NPC Barter Data from SQL + **/ +static void npc_barter_fromsql(void) +{ + struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle); + char name[NAME_LENGTH + 1]; + int itemid; + int amount; + int removeId; + int removeAmount; + + if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemId`, `amount`, `priceId`, `priceAmount` FROM `%s`", map->npc_barter_data_db) + || SQL_ERROR == SQL->StmtExecute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return; + } + + SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof name, NULL, NULL); + SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, sizeof itemid, NULL, NULL); + SQL->StmtBindColumn(stmt, 2, SQLDT_UINT32, &amount, sizeof amount, NULL, NULL); + SQL->StmtBindColumn(stmt, 3, SQLDT_INT, &removeId, sizeof removeId, NULL, NULL); + SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &removeAmount, sizeof removeAmount, NULL, NULL); + + while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) { + struct npc_data *nd = NULL; + unsigned short i; + + if (!(nd = npc->name2id(name))) { + ShowError("npc_barter_fromsql: NPC '%s' not found! skipping...\n",name); + npc->barter_delfromsql_sub(name, INT_MAX, 0, 0); + continue; + } else if (nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_BARTER) { + ShowError("npc_barter_fromsql: NPC '%s' is not proper for barter, skipping...\n",name); + npc->barter_delfromsql_sub(name, INT_MAX, 0, 0); + continue; + } + + for (i = 0; i < nd->u.scr.shop->items; i++) { + struct npc_item_list *const item = &nd->u.scr.shop->item[i]; + if (item->nameid == itemid && item->value == removeId && item->value2 == removeAmount) { + item->qty = amount; + break; + } + } + + if (i == nd->u.scr.shop->items) { + ShowError("npc_barter_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n", name, itemid, amount); + npc->barter_delfromsql_sub(name, itemid, removeId, removeAmount); + continue; + } + } + SQL->StmtFree(stmt); +} + +/** + * Saves persistent NPC Barter Data into SQL + **/ +static void npc_barter_tosql(struct npc_data *nd, int index) +{ + nullpo_retv(nd); + Assert_retv(index >= 0 && index < nd->u.scr.shop->items); + const struct npc_item_list *const item = &nd->u.scr.shop->item[index]; + if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s', '%d', '%u', '%u', '%d')", + map->npc_barter_data_db, nd->exname, item->nameid, item->qty, item->value, item->value2)) { + Sql_ShowDebug(map->mysql_handle); + } +} + +/** + * Removes persistent NPC Barter Data from SQL + */ +static void npc_barter_delfromsql_sub(const char *npcname, int itemId, int itemId2, int amount2) +{ + if (itemId == INT_MAX) { + if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_barter_data_db, npcname)) + Sql_ShowDebug(map->mysql_handle); + } else { + if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s' AND `itemId`='%d' AND `priceId`='%d' AND `priceAmount`='%d' LIMIT 1", + map->npc_barter_data_db, npcname, itemId, itemId2, amount2)) { + Sql_ShowDebug(map->mysql_handle); + } + } +} + +/** + * Removes persistent NPC Barter Data from SQL + **/ +static void npc_barter_delfromsql(struct npc_data *nd, int index) +{ + nullpo_retv(nd); + if (index == INT_MAX) { + npc->barter_delfromsql_sub(nd->exname, INT_MAX, 0, 0); + } else { + Assert_retv(index >= 0 && index < nd->u.scr.shop->items); + const struct npc_item_list *const item = &nd->u.scr.shop->item[index]; + npc->barter_delfromsql_sub(nd->exname, item->nameid, item->value, item->value2); + } +} + /** * Judges whether to allow and spawn a trader's window. **/ @@ -2151,20 +2254,23 @@ static int npc_barter_buylist(struct map_session_data *sd, struct barteritemlist if (n < 0 || n >= sd->status.inventorySize) return 11; // wrong inventory index + int removeId = sd->status.inventory[n].nameid; + const int j = entry->shopIndex; + if (j < 0 || j >= shop_size) + return 13; // no such item in shop + if (entry->addId != shop[j].nameid && entry->addId != itemdb_viewid(shop[j].nameid)) + return 13; // no such item in shop + if (removeId != shop[j].value && removeId != itemdb_viewid(shop[j].value)) + return 13; // no such item in shop + entry->addId = shop[j].nameid; // item_avail replacement + removeId = shop[j].value; // item_avail replacement + if (!itemdb->exists(entry->addId)) return 13; // item no longer in itemdb - const int removeId = sd->status.inventory[n].nameid; - int j = shop_size; - // find this entry in the shop's sell list - ARR_FIND(0, shop_size, j, (entry->addId == shop[j].nameid || entry->addId == itemdb_viewid(shop[j].nameid)) && - (removeId == shop[j].value || removeId == itemdb_viewid(shop[j].value))); - if (j == shop_size) - return 13; // no such item in shop - const int removeAmount = shop[j].value2; - if (entry->addAmount > (int)shop[j].qty) + if ((int)shop[j].qty != -1 && entry->addAmount > (int)shop[j].qty) return 14; // not enough item amount in shop if (removeAmount * entry->addAmount > sd->status.inventory[n].amount) @@ -2219,12 +2325,13 @@ static int npc_barter_buylist(struct map_session_data *sd, struct barteritemlist struct barter_itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); const int shopIdx = npc_market_qty[i]; - if (entry->addAmount > (int)shop[shopIdx].qty) /* wohoo someone tampered with the packet. */ - return 14; - - shop[shopIdx].qty -= entry->addAmount; + if ((int)shop[shopIdx].qty != -1) { + if (entry->addAmount > (int)shop[shopIdx].qty) /* wohoo someone tampered with the packet. */ + return 14; + shop[shopIdx].qty -= entry->addAmount; + } - // TODO: save to sql + npc->barter_tosql(nd, shopIdx); if (itemdb_type(entry->addId) == IT_PETEGG) { pet->create_egg(sd, entry->addId); @@ -5125,6 +5232,7 @@ static int npc_reload(void) // OnInit -> OnInterIfInit -> OnInterIfInitOnce -> OnAgitInit -> OnAgitInit2 npc->event_do_oninit( true ); npc->market_fromsql(); + npc->barter_fromsql(); // Execute rest of the startup events if connected to char-server. [Lance] // Executed when connection is established with char-server in chrif_connectack if( !intif->CheckForCharServer() ) { @@ -5437,6 +5545,10 @@ void npc_defaults(void) npc->market_tosql = npc_market_tosql; npc->market_delfromsql = npc_market_delfromsql; npc->market_delfromsql_sub = npc_market_delfromsql_sub; + npc->barter_fromsql = npc_barter_fromsql; + npc->barter_tosql = npc_barter_tosql; + npc->barter_delfromsql = npc_barter_delfromsql; + npc->barter_delfromsql_sub = npc_barter_delfromsql_sub; npc->db_checkid = npc_db_checkid; npc->refresh = npc_refresh; } |