Speed up item and mob information commands (#7084)

* Fixes #7081.
* Small refactor of the atcommands: iteminfo, mobinfo, whodrops, and idsearch.
* Item information gathering is now sped up.
* Refactored itemdb_searchname_array to store results in a std::map so that the data is sorted by ID automatically.
* Cleanups across the board to remove extra calls for itemdb_exists().
Thanks to @voyfmyuh, @CairoLee, and @Lemongrass3110!
This commit is contained in:
Aleos
2022-07-22 15:11:44 -04:00
committed by GitHub
parent e3cb3fa01f
commit 8038e71322
15 changed files with 255 additions and 184 deletions

View File

@@ -83,6 +83,19 @@ namespace rathena {
return defaultValue;
}
/**
* Resize a map.
* @param map: Map to resize
* @param size: Size to set map to
*/
template <typename K, typename V, typename S> void map_resize(std::map<K, V> &map, S size) {
auto it = map.begin();
std::advance(it, size);
map.erase(it, map.end());
}
/**
* Find a key-value pair and return the key value as a reference
* @param map: Unordered Map to search through
@@ -129,6 +142,15 @@ namespace rathena {
return defaultValue;
}
/**
* Resize an unordered map.
* @param map: Unordered map to resize
* @param size: Size to set unordered map to
*/
template <typename K, typename V, typename S> void umap_resize(std::unordered_map<K, V> &map, S size) {
map.erase(std::advance(map.begin(), map.min(size, map.size())), map.end());
}
/**
* Get a random value from the given unordered map
* @param map: Unordered Map to search through

View File

@@ -3911,28 +3911,33 @@ ACMD_FUNC(mapexit)
*------------------------------------------*/
ACMD_FUNC(idsearch)
{
char item_name[100];
uint16 i, match;
struct item_data *item_array[MAX_SEARCH];
nullpo_retr(-1, sd);
char item_name[100];
memset(item_name, '\0', sizeof(item_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99s", item_name) < 0) {
clif_displaymessage(fd, msg_txt(sd,1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>).
return -1;
}
memset(atcmd_output, '\0', sizeof(atcmd_output));
sprintf(atcmd_output, msg_txt(sd,77), item_name); // The reference result of '%s' (name: id):
clif_displaymessage(fd, atcmd_output);
match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name);
std::map<t_itemid, std::shared_ptr<item_data>> item_array = {};
uint16 match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name);
if (match == MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(sd,269), MAX_SEARCH); // Displaying first %d matches
clif_displaymessage(fd, atcmd_output);
}
for(i = 0; i < match; i++) {
sprintf(atcmd_output, msg_txt(sd,78), item_array[i]->ename.c_str(), item_array[i]->nameid); // %s: %u
for(const auto &result : item_array) {
std::shared_ptr<item_data> id = result.second;
sprintf(atcmd_output, msg_txt(sd,78), id->ename.c_str(), id->nameid); // %s: %u
clif_displaymessage(fd, atcmd_output);
}
sprintf(atcmd_output, msg_txt(sd,79), match); // It is %d affair above.
@@ -5840,7 +5845,6 @@ ACMD_FUNC(dropall)
{
int8 type = -1;
uint16 i, count = 0, count2 = 0;
struct item_data *item_data = NULL;
nullpo_retr(-1, sd);
@@ -5857,14 +5861,16 @@ ACMD_FUNC(dropall)
for( i = 0; i < MAX_INVENTORY; i++ ) {
if( sd->inventory.u.items_inventory[i].amount ) {
if( (item_data = itemdb_exists(sd->inventory.u.items_inventory[i].nameid)) == NULL ) {
std::shared_ptr<item_data> id = item_db.find(sd->inventory.u.items_inventory[i].nameid);
if( id == nullptr ) {
ShowDebug("Non-existant item %d on dropall list (account_id: %d, char_id: %d)\n", sd->inventory.u.items_inventory[i].nameid, sd->status.account_id, sd->status.char_id);
continue;
}
if( !pc_candrop(sd,&sd->inventory.u.items_inventory[i]) )
continue;
if( type == -1 || type == (uint8)item_data->type ) {
if( type == -1 || type == (uint8)id->type ) {
if( sd->inventory.u.items_inventory[i].equip != 0 )
pc_unequipitem(sd, i, 3);
if( itemdb_ishatched_egg( &sd->inventory.u.items_inventory[i] ) ){
@@ -7612,9 +7618,8 @@ ACMD_FUNC(mobinfo)
unsigned char mrace[RC_ALL][11] = { "Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Player" };
unsigned char melement[ELE_ALL][8] = { "Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead" };
char atcmd_output2[CHAT_SIZE_MAX];
struct item_data *item_data;
uint16 mob_ids[MAX_SEARCH], count;
int i, k;
uint16 i;
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_output2, '\0', sizeof(atcmd_output2));
@@ -7625,7 +7630,7 @@ ACMD_FUNC(mobinfo)
}
// If monster identifier/name argument is a name
if ((i = mobdb_checkid(atoi(message))))
if ((i = mobdb_checkid(strtoul(message, nullptr, 10))))
{
mob_ids[0] = i;
count = 1;
@@ -7642,7 +7647,7 @@ ACMD_FUNC(mobinfo)
clif_displaymessage(fd, atcmd_output);
count = MAX_SEARCH;
}
for (k = 0; k < count; k++) {
for (uint16 k = 0; k < count; k++) {
std::shared_ptr<s_mob_db> mob = mob_db.find(mob_ids[k]);
if (mob == nullptr)
@@ -7697,15 +7702,21 @@ ACMD_FUNC(mobinfo)
#endif
for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
if (mob->dropitem[i].nameid == 0 || mob->dropitem[i].rate < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL)
if (mob->dropitem[i].nameid == 0 || mob->dropitem[i].rate < 1)
continue;
std::shared_ptr<item_data> id = item_db.find(mob->dropitem[i].nameid);
if (id == nullptr)
continue;
int droprate = mob_getdroprate( &sd->bl, mob, mob->dropitem[i].rate, drop_modifier );
if (item_data->slots)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->ename.c_str(), item_data->slots, (float)droprate / 100);
if (id->slots)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", id->ename.c_str(), id->slots, (float)droprate / 100);
else
sprintf(atcmd_output2, " - %s %02.02f%%", item_data->ename.c_str(), (float)droprate / 100);
sprintf(atcmd_output2, " - %s %02.02f%%", id->ename.c_str(), (float)droprate / 100);
strcat(atcmd_output, atcmd_output2);
if (++j % 3 == 0) {
clif_displaymessage(fd, atcmd_output);
@@ -7725,8 +7736,15 @@ ACMD_FUNC(mobinfo)
mvpremain = 100.0; //Remaining drop chance for official mvp drop mode
j = 0;
for (i = 0; i < MAX_MVP_DROP_TOTAL; i++) {
if (mob->mvpitem[i].nameid == 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL)
if (mob->mvpitem[i].nameid == 0)
continue;
std::shared_ptr<item_data> id = item_db.find(mob->mvpitem[i].nameid);
if (id == nullptr)
continue;
//Because if there are 3 MVP drops at 50%, the first has a chance of 50%, the second 25% and the third 12.5%
mvppercent = (float)mob->mvpitem[i].rate * mvpremain / 10000.0f;
if(battle_config.item_drop_mvp_mode == 0) {
@@ -7735,15 +7753,15 @@ ACMD_FUNC(mobinfo)
if (mvppercent > 0) {
j++;
if (j == 1) {
if (item_data->slots)
sprintf(atcmd_output2, " %s[%d] %02.02f%%", item_data->ename.c_str(), item_data->slots, mvppercent);
if (id->slots)
sprintf(atcmd_output2, " %s[%d] %02.02f%%", id->ename.c_str(), id->slots, mvppercent);
else
sprintf(atcmd_output2, " %s %02.02f%%", item_data->ename.c_str(), mvppercent);
sprintf(atcmd_output2, " %s %02.02f%%", id->ename.c_str(), mvppercent);
} else {
if (item_data->slots)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->ename.c_str(), item_data->slots, mvppercent);
if (id->slots)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", id->ename.c_str(), id->slots, mvppercent);
else
sprintf(atcmd_output2, " - %s %02.02f%%", item_data->ename.c_str(), mvppercent);
sprintf(atcmd_output2, " - %s %02.02f%%", id->ename.c_str(), mvppercent);
}
strcat(atcmd_output, atcmd_output2);
}
@@ -8149,15 +8167,21 @@ ACMD_FUNC(homshuffle)
*------------------------------------------*/
ACMD_FUNC(iteminfo)
{
struct item_data *item_array[MAX_SEARCH];
uint16 i, count = 1;
if (!message || !*message) {
clif_displaymessage(fd, msg_txt(sd,1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>).
return -1;
}
if ((item_array[0] = itemdb_exists(strtoul(message, nullptr, 10))) == nullptr)
std::map<t_itemid, std::shared_ptr<item_data>> item_array = {};
uint16 count = 1;
t_itemid itemid = strtoul(message, nullptr, 10);
if (itemid == 0) // Entered a string
count = itemdb_searchname_array(item_array, MAX_SEARCH, message);
else {
if ((item_array[0] = item_db.find(itemid)) == nullptr)
count = 0;
}
if (!count) {
clif_displaymessage(fd, msg_txt(sd,19)); // Invalid item ID or name.
@@ -8168,8 +8192,9 @@ ACMD_FUNC(iteminfo)
sprintf(atcmd_output, msg_txt(sd,269), MAX_SEARCH); // Displaying first %d matches
clif_displaymessage(fd, atcmd_output);
}
for (i = 0; i < count; i++) {
struct item_data * item_data = item_array[i];
for (const auto &result : item_array) {
std::shared_ptr<item_data> item_data = result.second;
sprintf(atcmd_output, msg_txt(sd,1277), // Item: '%s'/'%s'[%d] (%u) Type: %s | Extra Effect: %s
item_data->name.c_str(),item_data->ename.c_str(),item_data->slots,item_data->nameid,
(item_data->type != IT_AMMO) ? itemdb_typename((enum item_types)item_data->type) : itemdb_typename_ammo((e_ammo_type)item_data->subtype),
@@ -8200,15 +8225,21 @@ ACMD_FUNC(iteminfo)
*------------------------------------------*/
ACMD_FUNC(whodrops)
{
struct item_data *item_data, *item_array[MAX_SEARCH];
uint16 i, j, count = 1;
if (!message || !*message) {
clif_displaymessage(fd, msg_txt(sd,1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>).
return -1;
}
if ((item_array[0] = itemdb_exists(strtoul(message, nullptr, 10))) == nullptr)
std::map<t_itemid, std::shared_ptr<item_data>> item_array = {};
uint16 count = 1;
t_itemid itemid = strtoul(message, nullptr, 10);
if (itemid == 0) // Entered a string
count = itemdb_searchname_array(item_array, MAX_SEARCH, message);
else {
if ((item_array[0] = item_db.find(itemid)) == nullptr)
count = 0;
}
if (!count) {
clif_displaymessage(fd, msg_txt(sd,19)); // Invalid item ID or name.
@@ -8219,22 +8250,23 @@ ACMD_FUNC(whodrops)
sprintf(atcmd_output, msg_txt(sd,269), MAX_SEARCH); // Displaying first %d matches
clif_displaymessage(fd, atcmd_output);
}
for (i = 0; i < count; i++) {
item_data = item_array[i];
sprintf(atcmd_output, msg_txt(sd,1285), item_data->ename.c_str(), item_data->slots, item_data->nameid); // Item: '%s'[%d] (ID:%u)
for (const auto &result : item_array) {
std::shared_ptr<item_data> id = result.second;
sprintf(atcmd_output, msg_txt(sd,1285), id->ename.c_str(), id->slots, id->nameid); // Item: '%s'[%d] (ID:%u)
clif_displaymessage(fd, atcmd_output);
if (item_data->mob[0].chance == 0) {
if (id->mob[0].chance == 0) {
strcpy(atcmd_output, msg_txt(sd,1286)); // - Item is not dropped by mobs.
clif_displaymessage(fd, atcmd_output);
} else {
sprintf(atcmd_output, msg_txt(sd,1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed):
clif_displaymessage(fd, atcmd_output);
for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++)
for (uint16 j=0; j < MAX_SEARCH && id->mob[j].chance > 0; j++)
{
int dropchance = item_data->mob[j].chance;
std::shared_ptr<s_mob_db> mob = mob_db.find(item_data->mob[j].id);
int dropchance = id->mob[j].chance;
std::shared_ptr<s_mob_db> mob = mob_db.find(id->mob[j].id);
if(!mob) continue;
#ifdef RENEWAL_DROP
@@ -8246,7 +8278,7 @@ ACMD_FUNC(whodrops)
#endif
if (pc_isvip(sd)) // Display item rate increase for VIP
dropchance += (dropchance * battle_config.vip_drop_increase) / 100;
sprintf(atcmd_output, "- %s (%d): %02.02f%%", mob->jname.c_str(), item_data->mob[j].id, dropchance/100.);
sprintf(atcmd_output, "- %s (%d): %02.02f%%", mob->jname.c_str(), id->mob[j].id, dropchance/100.);
clif_displaymessage(fd, atcmd_output);
}
}
@@ -9198,9 +9230,13 @@ ACMD_FUNC(itemlist)
counter = 0; // total items found
for( i = 0; i < size; ++i ) {
const struct item* it = &items[i];
struct item_data* itd;
if( it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL )
if( it->nameid == 0 )
continue;
std::shared_ptr<item_data> itd = item_db.find(it->nameid);
if (itd == nullptr)
continue;
counter += it->amount;
@@ -9302,9 +9338,12 @@ ACMD_FUNC(itemlist)
int counter2 = 0;
for( j = 0; j < itd->slots; ++j ) {
struct item_data* card;
if( it->card[j] == 0 )
continue;
if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL )
std::shared_ptr<item_data> card = item_db.find(it->card[j]);
if (card == nullptr)
continue;
counter2++;

View File

@@ -162,11 +162,10 @@ int8 buyingstore_create( struct map_session_data* sd, int zenylimit, unsigned ch
// check item list
for( i = 0; i < count; i++ ){
const struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub *item = &itemlist[i];
struct item_data* id = itemdb_exists( item->itemId );
std::shared_ptr<item_data> id = item_db.find(item->itemId);
// invalid input
if( id == NULL || item->amount == 0 ){
if( id == nullptr || item->amount == 0 ){
break;
}
@@ -176,7 +175,7 @@ int8 buyingstore_create( struct map_session_data* sd, int zenylimit, unsigned ch
}
// restrictions: allowed and no character-bound items
if( !id->flag.buyingstore || !itemdb_cantrade_sub( id, pc_get_group_level( sd ), pc_get_group_level( sd ) ) ){
if( !id->flag.buyingstore || !itemdb_cantrade_sub( id.get(), pc_get_group_level( sd ), pc_get_group_level( sd ) ) ){
break;
}

View File

@@ -471,7 +471,6 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, s
uint32 totalcash = 0;
uint32 totalweight = 0;
int i,new_;
item_data *id;
if( sd == NULL || item_list == NULL || !cash_shop_defined){
clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_UNKNOWN );
@@ -502,7 +501,8 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, s
}
nameid = item_list[i].itemId = cash_shop_items[tab].item[j]->nameid; //item_avail replacement
id = itemdb_exists(nameid);
std::shared_ptr<item_data> id = item_db.find(nameid);
if( !id ){
clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKONWN_ITEM );

View File

@@ -2193,10 +2193,10 @@ void clif_buylist( struct map_session_data *sd, struct npc_data *nd ){
p->items[count].itemType = itemtype( nd->u.shop.shop_item[i].nameid );
p->items[count].itemId = client_nameid( nd->u.shop.shop_item[i].nameid );
#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
struct item_data* id = itemdb_exists( nd->u.shop.shop_item[i].nameid );
std::shared_ptr<item_data> id = item_db.find(nd->u.shop.shop_item[i].nameid);
p->items[count].viewSprite = id->look;
p->items[count].location = pc_equippoint_sub( sd, id );
p->items[count].location = pc_equippoint_sub( sd, id.get() );
#endif
count++;
}
@@ -2279,7 +2279,7 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
continue;
}
struct item_data *id = itemdb_exists( item->nameid );
std::shared_ptr<item_data> id = item_db.find(item->nameid);
if( !id ){
continue;
@@ -2296,7 +2296,7 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
p->list[count].qty = item->qty;
p->list[count].weight = id->weight;
#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
p->list[count].location = pc_equippoint_sub( sd, id );
p->list[count].location = pc_equippoint_sub( sd, id.get() );
#endif
count++;
}
@@ -16215,7 +16215,6 @@ void clif_Mail_read( struct map_session_data *sd, int mail_id ){
} else {
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item;
struct item_data *data;
int msg_len = strlen(msg->body);
if( msg_len == 0 ) {
@@ -16273,7 +16272,9 @@ void clif_Mail_read( struct map_session_data *sd, int mail_id ){
for( int j = 0; j < MAIL_MAX_ITEM; j++ ){
item = &msg->item[j];
if( item->nameid > 0 && item->amount > 0 && ( data = itemdb_exists( item->nameid ) ) != NULL ){
std::shared_ptr<item_data> data = item_db.find(item->nameid);
if( item->nameid > 0 && item->amount > 0 && data != nullptr ){
struct PACKET_ZC_ACK_READ_RODEX_SUB* mailitem = (struct PACKET_ZC_ACK_READ_RODEX_SUB*)WBUFP( p, p->PacketLength );
mailitem->ITID = client_nameid( item->nameid );
@@ -16282,7 +16283,7 @@ void clif_Mail_read( struct map_session_data *sd, int mail_id ){
mailitem->IsIdentified = item->identify ? 1 : 0;
mailitem->IsDamaged = item->attribute ? 1 : 0;
mailitem->refiningLevel = item->refine;
mailitem->location = pc_equippoint_sub( sd, data );
mailitem->location = pc_equippoint_sub( sd, data.get() );
mailitem->viewSprite = data->look;
mailitem->bindOnEquip = item->bound ? 2 : data->flag.bindOnEquip ? 1 : 0;
clif_addcards( &mailitem->slot, item );
@@ -16476,9 +16477,9 @@ void clif_parse_Mail_getattach( int fd, struct map_session_data *sd ){
struct item* item = &msg->item[i];
if( item->nameid > 0 && item->amount > 0 ){
struct item_data *data;
std::shared_ptr<item_data> data = item_db.find(item->nameid);
if((data = itemdb_exists(item->nameid)) == NULL)
if(data == nullptr)
continue;
switch( pc_checkadditem(sd, item->nameid, item->amount) ){
@@ -16845,7 +16846,6 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd){
struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
int idx = RFIFOW(fd,info->pos[0]) - 2;
int amount = RFIFOL(fd,info->pos[1]); // Always 1
struct item_data *item;
if( !battle_config.feature_auction )
return;
@@ -16863,7 +16863,9 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd){
return;
}
if( (item = itemdb_exists(sd->inventory.u.items_inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC || item->type == IT_SHADOWGEAR) )
std::shared_ptr<item_data> id = item_db.find(sd->inventory.u.items_inventory[idx].nameid);
if( id != nullptr && !(id->type == IT_ARMOR || id->type == IT_PETARMOR || id->type == IT_WEAPON || id->type == IT_CARD || id->type == IT_ETC || id->type == IT_SHADOWGEAR) )
{ // Consumable or pets are not allowed
clif_Auction_setitem(sd->fd, idx, true);
return;
@@ -16925,7 +16927,6 @@ void clif_Auction_close(int fd, unsigned char flag)
void clif_parse_Auction_register(int fd, struct map_session_data *sd)
{
struct auction_data auction;
struct item_data *item;
struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
if( !battle_config.feature_auction )
@@ -16980,14 +16981,16 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
return;
}
if( (item = itemdb_exists(sd->inventory.u.items_inventory[sd->auction.index].nameid)) == NULL )
std::shared_ptr<item_data> id = item_db.find(sd->inventory.u.items_inventory[sd->auction.index].nameid);
if( id == nullptr )
{ // Just in case
clif_Auction_message(fd, 2); // The auction has been canceled
return;
}
safestrncpy(auction.item_name, item->ename.c_str(), sizeof(auction.item_name));
auction.type = item->type;
safestrncpy(auction.item_name, id->ename.c_str(), sizeof(auction.item_name));
auction.type = id->type;
memcpy(&auction.item, &sd->inventory.u.items_inventory[sd->auction.index], sizeof(struct item));
auction.item.amount = 1;
auction.timestamp = 0;
@@ -22788,7 +22791,7 @@ void clif_barter_open( struct map_session_data& sd, struct npc_data& nd ){
int16 count = 0;
for( const auto& itemPair : barter->items ){
struct PACKET_ZC_NPC_BARTER_MARKET_ITEMINFO_sub* item = &p->list[count];
struct item_data* id = itemdb_exists( itemPair.second->nameid );
std::shared_ptr<item_data> id = item_db.find(itemPair.second->nameid);
item->nameid = client_nameid( id->nameid );
item->type = itemtype( id->nameid );
@@ -22801,7 +22804,7 @@ void clif_barter_open( struct map_session_data& sd, struct npc_data& nd ){
item->index = itemPair.second->index;
#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
item->viewSprite = id->look;
item->location = pc_equippoint_sub( &sd, id );
item->location = pc_equippoint_sub( &sd, id.get() );
#endif
// Use a loop if someone did not start with index 0
@@ -22938,7 +22941,7 @@ void clif_barter_extended_open( struct map_session_data& sd, struct npc_data& nd
for( const auto& itemPair : barter->items ){
// Needs dynamic calculation, because of variable currencies
struct PACKET_ZC_NPC_EXPANDED_BARTER_MARKET_ITEMINFO_sub* item = (struct PACKET_ZC_NPC_EXPANDED_BARTER_MARKET_ITEMINFO_sub*)( ( (uint8*)p ) + p->packetLength );
struct item_data* id = itemdb_exists( itemPair.second->nameid );
std::shared_ptr<item_data> id = item_db.find(itemPair.second->nameid);
item->nameid = client_nameid( id->nameid );
item->type = itemtype( id->nameid );
@@ -22952,7 +22955,7 @@ void clif_barter_extended_open( struct map_session_data& sd, struct npc_data& nd
item->zeny = itemPair.second->price;
#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
item->viewSprite = id->look;
item->location = pc_equippoint_sub( &sd, id );
item->location = pc_equippoint_sub( &sd, id.get() );
#endif
p->packetLength += (int16)( sizeof( *item ) - sizeof( item->currencies ) );

View File

@@ -4,7 +4,6 @@
#include "itemdb.hpp"
#include <iostream>
#include <map>
#include <stdlib.h>
#include "../common/nullpo.hpp"
@@ -1670,22 +1669,21 @@ LaphineUpgradeDatabase laphine_upgrade_db;
* @param str
* @return Number of matches item
*------------------------------------------*/
uint16 itemdb_searchname_array(struct item_data** data, uint16 size, const char *str)
uint16 itemdb_searchname_array(std::map<t_itemid, std::shared_ptr<item_data>> &data, uint16 size, const char *str)
{
uint16 count = 0;
const auto &item_list = item_db.getCache();
for (const auto &item : item_db) {
std::shared_ptr<item_data> id = item.second;
for (const auto &item : item_list) {
if (item == nullptr)
if (id == nullptr)
continue;
if (count < size) {
if (stristr(item->name.c_str(), str) != nullptr || stristr(item->ename.c_str(), str) != nullptr || strcmpi(item->ename.c_str(), str) == 0)
data[count++] = item.get();
} else
break;
if (stristr(id->name.c_str(), str) != nullptr || stristr(id->ename.c_str(), str) != nullptr || strcmpi(id->ename.c_str(), str) == 0)
data[id->nameid] = id;
}
return count;
if (data.size() > size)
util::map_resize(data, size);
return static_cast<uint16>(data.size());
}
std::shared_ptr<s_item_group_entry> get_random_itemsubgroup(std::shared_ptr<s_item_group_random> random) {
@@ -1844,10 +1842,8 @@ uint8 ItemGroupDatabase::pc_get_itemgroup(uint16 group_id, bool identify, map_se
* @param nameid
* @return *item_data if item is exist, or NULL if not
*/
struct item_data* itemdb_exists(t_itemid nameid) {
std::shared_ptr<item_data> item = item_db.find(nameid);
return item ? item.get() : nullptr;
std::shared_ptr<item_data> itemdb_exists(t_itemid nameid) {
return item_db.find(nameid);
}
/// Returns name type of ammunition [Cydh]
@@ -2366,12 +2362,13 @@ void ItemGroupDatabase::loadingFinished() {
static bool itemdb_read_noequip(char* str[], int columns, int current) {
t_itemid nameid;
int flag;
struct item_data *id;
nameid = strtoul(str[0], nullptr, 10);
flag = atoi(str[1]);
if( ( id = itemdb_exists(nameid) ) == NULL )
std::shared_ptr<item_data> id = item_db.find(nameid);
if( id == nullptr )
{
ShowWarning("itemdb_read_noequip: Invalid item id %u.\n", nameid);
return false;
@@ -2530,8 +2527,10 @@ void ComboDatabase::loadingFinished() {
// Populate item_data to refer to the combo
for (const auto &combo : *this) {
for (const auto &itm : combo.second->nameid) {
item_data *it = itemdb_exists(itm);
it->combos.push_back(combo.second);
std::shared_ptr<item_data> it = item_db.find(itm);
if (it != nullptr)
it->combos.push_back(combo.second);
}
}

View File

@@ -1385,9 +1385,9 @@ public:
extern LaphineUpgradeDatabase laphine_upgrade_db;
uint16 itemdb_searchname_array(struct item_data** data, uint16 size, const char *str);
uint16 itemdb_searchname_array(std::map<t_itemid, std::shared_ptr<item_data>> &data, uint16 size, const char *str);
struct item_data* itemdb_search(t_itemid nameid);
struct item_data* itemdb_exists(t_itemid nameid);
std::shared_ptr<item_data> itemdb_exists(t_itemid nameid);
#define itemdb_name(n) itemdb_search(n)->name.c_str()
#define itemdb_ename(n) itemdb_search(n)->ename.c_str()
#define itemdb_type(n) itemdb_search(n)->type

View File

@@ -144,9 +144,9 @@ static char log_feedingtype2char(e_log_feeding_type type) {
static bool should_log_item(t_itemid nameid, int amount, int refine)
{
int filter = log_config.filter;
struct item_data* id;
std::shared_ptr<item_data> id = item_db.find(nameid);
if( ( id = itemdb_exists(nameid) ) == NULL )
if( id == nullptr )
return false;
if( ( filter&LOG_FILTER_ALL ) ||

View File

@@ -313,7 +313,7 @@ std::shared_ptr<s_mob_db> mobdb_search_aegisname( const char* str ){
}
/*==========================================
* Founds up to N matches. Returns number of matches [Skotlex]
* Searches up to N matches. Returns number of matches [Skotlex]
*------------------------------------------*/
uint16 mobdb_searchname_array_(const char *str, uint16 * out, uint16 size, bool full_cmp)
{
@@ -2787,7 +2787,6 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
{ // Item Drop
struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
struct item_drop *ditem;
struct item_data* it = NULL;
int drop_rate, drop_modifier = 100;
#ifdef RENEWAL_DROP
@@ -2804,7 +2803,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
if (md->db->dropitem[i].nameid == 0)
continue;
if ( !(it = itemdb_exists(md->db->dropitem[i].nameid)) )
std::shared_ptr<item_data> it = item_db.find(md->db->dropitem[i].nameid);
if ( it == nullptr )
continue;
drop_rate = mob_getdroprate(src, md->db, md->db->dropitem[i].rate, drop_modifier);
@@ -2966,9 +2968,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
#endif
for(i = 0; i < MAX_MVP_DROP_TOTAL; i++) {
struct item_data *i_data;
if(mdrop[i].nameid == 0)
continue;
if(mdrop[i].nameid == 0 || !(i_data = itemdb_exists(mdrop[i].nameid)))
std::shared_ptr<item_data> i_data = item_db.find(mdrop[i].nameid);
if (i_data == nullptr)
continue;
temp = mdrop[i].rate;

View File

@@ -2343,7 +2343,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
break;
case NPCTYPE_ITEMSHOP:
{
struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
std::shared_ptr<item_data> id = item_db.find(nd->u.shop.itemshop_nameid);
int delete_amount = price, i;
if (!id) { // Item Data is checked at script parsing but in case of item_db reload, check again.
@@ -2418,7 +2418,6 @@ int npc_cashshop_buylist( struct map_session_data *sd, int points, std::vector<s
t_itemid nameid;
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
enum e_CASHSHOP_ACK res;
item_data *id;
if( !nd || ( nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) )
return ERROR_TYPE_NPC;
@@ -2434,7 +2433,8 @@ int npc_cashshop_buylist( struct map_session_data *sd, int points, std::vector<s
{
nameid = item_list[i].nameid;
amount = item_list[i].qty;
id = itemdb_exists(nameid);
std::shared_ptr<item_data> id = item_db.find(nameid);
if( !id || amount <= 0 )
return ERROR_TYPE_ITEM_ID;
@@ -2445,7 +2445,7 @@ int npc_cashshop_buylist( struct map_session_data *sd, int points, std::vector<s
nameid = item_list[i].nameid = nd->u.shop.shop_item[j].nameid; //item_avail replacement
if( !itemdb_isstackable2(id) && amount > 1 )
if( !itemdb_isstackable2(id.get()) && amount > 1 )
{
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i].qty = 1;
@@ -2529,7 +2529,7 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in
case NPCTYPE_ITEMSHOP:
{
int total = 0, i;
struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
std::shared_ptr<item_data> id = item_db.find(nd->u.shop.itemshop_nameid);
if (id) { // Item Data is checked at script parsing but in case of item_db reload, check again.
if (display) {
@@ -2576,7 +2576,6 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in
int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, int points)
{
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
struct item_data *item;
int i, price, w;
enum e_CASHSHOP_ACK res;
@@ -2592,7 +2591,9 @@ int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, i
if( sd->state.trading )
return ERROR_TYPE_EXCHANGE;
if( (item = itemdb_exists(nameid)) == NULL )
std::shared_ptr<item_data> id = item_db.find(nameid);
if( id == nullptr )
return ERROR_TYPE_ITEM_ID; // Invalid Item
ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid || itemdb_viewid(nd->u.shop.shop_item[i].nameid) == nameid);
@@ -2603,7 +2604,7 @@ int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, i
nameid = nd->u.shop.shop_item[i].nameid; //item_avail replacement
if(!itemdb_isstackable2(item) && amount > 1)
if(!itemdb_isstackable2(id.get()) && amount > 1)
{
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
@@ -2613,20 +2614,20 @@ int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, i
switch( pc_checkadditem(sd, nameid, amount) )
{
case CHKADDITEM_NEW:
if( pc_inventoryblank(sd) < item->inventorySlotNeeded(amount) )
if( pc_inventoryblank(sd) < id->inventorySlotNeeded(amount) )
return ERROR_TYPE_INVENTORY_WEIGHT;
break;
case CHKADDITEM_OVERAMOUNT:
return ERROR_TYPE_INVENTORY_WEIGHT;
}
w = item->weight * amount;
w = id->weight * amount;
if( w + sd->weight > sd->max_weight )
return ERROR_TYPE_INVENTORY_WEIGHT;
if( (double)nd->u.shop.shop_item[i].value * amount > INT_MAX )
{
ShowWarning("npc_cashshop_buy: Item '%s' (%u) price overflow attempt!\n", item->name.c_str(), nameid);
ShowWarning("npc_cashshop_buy: Item '%s' (%u) price overflow attempt!\n", id->name.c_str(), nameid);
ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n",
nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount);
return ERROR_TYPE_ITEM_ID;
@@ -2647,7 +2648,7 @@ int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, i
item_tmp.nameid = nameid;
item_tmp.identify = 1;
if (item->flag.guid)
if (id->flag.guid)
get_amt = 1;
for (int j = 0; j < amount; j += get_amt)
@@ -2722,7 +2723,6 @@ e_purchase_result npc_buylist( struct map_session_data* sd, std::vector<s_npc_bu
t_itemid nameid;
unsigned short amount;
int value;
item_data *id;
// find this entry in the shop's sell list
ARR_FIND( 0, nd->u.shop.count, j,
@@ -2744,12 +2744,13 @@ e_purchase_result npc_buylist( struct map_session_data* sd, std::vector<s_npc_bu
amount = item_list[i].qty;
nameid = item_list[i].nameid = shop[j].nameid; //item_avail replacement
value = shop[j].value;
id = itemdb_exists(nameid);
std::shared_ptr<item_data> id = item_db.find(nameid);
if( !id )
return e_purchase_result::PURCHASE_FAIL_COUNT; // item no longer in itemdb
if( !itemdb_isstackable2(id) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O
if( !itemdb_isstackable2(id.get()) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i].qty = 1;
@@ -3046,7 +3047,7 @@ e_purchase_result npc_barter_purchase( struct map_session_data& sd, std::shared_
uint32 requiredItems[MAX_INVENTORY] = { 0 };
for( s_barter_purchase& purchase : purchases ){
purchase.data = itemdb_exists( purchase.item->nameid );
purchase.data = item_db.find( purchase.item->nameid ).get();
if( purchase.data == nullptr ){
return e_purchase_result::PURCHASE_FAIL_EXCHANGE_FAILED;
@@ -3071,14 +3072,13 @@ e_purchase_result npc_barter_purchase( struct map_session_data& sd, std::shared_
for( const auto& requirementPair : purchase.item->requirements ){
std::shared_ptr<s_npc_barter_requirement> requirement = requirementPair.second;
item_data* id = itemdb_exists( requirement->nameid );
std::shared_ptr<item_data> id = item_db.find(requirement->nameid);
if( id == nullptr ){
return e_purchase_result::PURCHASE_FAIL_EXCHANGE_FAILED;
}
if( itemdb_isstackable2( id ) ){
if( itemdb_isstackable2( id.get() ) ){
int j;
for( j = 0; j < MAX_INVENTORY; j++ ){
@@ -3985,7 +3985,6 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
t_itemid nameid2;
int32 qty = -1;
int value;
struct item_data* id;
bool skip = false;
if( p == NULL )
@@ -4010,7 +4009,9 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
if (skip)
break;
if( (id = itemdb_exists(nameid2)) == NULL ) {
std::shared_ptr<item_data> id = item_db.find(nameid2);
if( id == nullptr ) {
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%u').\n", filepath, strline(buffer,start-buffer), nameid2);
p = strchr(p+1,',');
continue;

View File

@@ -6138,17 +6138,17 @@ int pc_show_steal(struct block_list *bl,va_list ap)
{
struct map_session_data *sd;
t_itemid itemid;
struct item_data *item=NULL;
char output[100];
sd=va_arg(ap,struct map_session_data *);
itemid=va_arg(ap,int);
if((item=itemdb_exists(itemid))==NULL)
std::shared_ptr<item_data> id = item_db.find(itemid);
if(id == nullptr)
sprintf(output,"%s stole an Unknown Item (id: %u).",sd->status.name, itemid);
else
sprintf(output,"%s stole %s.",sd->status.name,item->ename.c_str());
sprintf(output,"%s stole %s.",sd->status.name,id->ename.c_str());
clif_displaymessage( ((struct map_session_data *)bl)->fd, output);
return 0;
@@ -11314,15 +11314,15 @@ int pc_load_combo(struct map_session_data *sd) {
ret += pc_checkcombo(sd, id);
if (!itemdb_isspecial(sd->inventory.u.items_inventory[idx].card[0])) {
item_data *data;
for (uint8 j = 0; j < MAX_SLOTS; j++) {
if (!sd->inventory.u.items_inventory[idx].card[j])
continue;
if ((data = itemdb_exists(sd->inventory.u.items_inventory[idx].card[j])) != nullptr) {
std::shared_ptr<item_data> data = item_db.find(sd->inventory.u.items_inventory[idx].card[j]);
if (data != nullptr) {
if (!data->combos.empty())
ret += pc_checkcombo(sd, data);
ret += pc_checkcombo(sd, data.get());
}
}
}
@@ -11415,7 +11415,7 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos,bool equipswit
if (!sd->inventory.u.items_inventory[n].card[i])
continue;
struct item_data *card_data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]);
std::shared_ptr<item_data> card_data = item_db.find(sd->inventory.u.items_inventory[n].card[i]);
if (card_data) {
int card_pos = card_data->equip;
@@ -11560,13 +11560,14 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos,bool equipswit
; // No cards
else {
for (i = 0; i < MAX_SLOTS; i++) {
item_data *data;
if (!sd->inventory.u.items_inventory[n].card[i])
continue;
if ((data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i])) != nullptr) {
std::shared_ptr<item_data> data = item_db.find(sd->inventory.u.items_inventory[n].card[i]);
if (data != nullptr) {
if (!data->combos.empty())
pc_checkcombo(sd, data);
pc_checkcombo(sd, data.get());
}
}
}
@@ -11584,11 +11585,13 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos,bool equipswit
; //No cards
else {
for( i = 0; i < MAX_SLOTS; i++ ) {
struct item_data *data;
if (!sd->inventory.u.items_inventory[n].card[i])
continue;
if ( ( data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i]) ) != NULL ) {
if (data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m)))
std::shared_ptr<item_data> data = item_db.find(sd->inventory.u.items_inventory[n].card[i]);
if ( data != nullptr ) {
if (data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data.get(), sd->bl.m)))
run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
}
}
@@ -11645,13 +11648,14 @@ static void pc_unequipitem_sub(struct map_session_data *sd, int n, int flag) {
; // No cards
else {
for (i = 0; i < MAX_SLOTS; i++) {
item_data *data;
if (!sd->inventory.u.items_inventory[n].card[i])
continue;
if ((data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i])) != nullptr) {
std::shared_ptr<item_data> data = item_db.find(sd->inventory.u.items_inventory[n].card[i]);
if (data != nullptr) {
if (!data->combos.empty()) {
if (pc_removecombo(sd, data))
if (pc_removecombo(sd, data.get()))
status_calc = true;
}
}
@@ -11675,11 +11679,12 @@ static void pc_unequipitem_sub(struct map_session_data *sd, int n, int flag) {
; //No cards
else {
for (i = 0; i < MAX_SLOTS; i++) {
struct item_data *data;
if (!sd->inventory.u.items_inventory[n].card[i])
continue;
if ((data = itemdb_exists(sd->inventory.u.items_inventory[n].card[i])) != NULL) {
std::shared_ptr<item_data> data = item_db.find(sd->inventory.u.items_inventory[n].card[i]);
if (data != nullptr) {
if (data->unequip_script)
run_script(data->unequip_script, 0, sd->bl.id, fake_nd->bl.id);
}

View File

@@ -14215,13 +14215,10 @@ BUILDIN_FUNC(getitemname)
*------------------------------------------*/
BUILDIN_FUNC(getitemslots)
{
struct item_data *i_data;
t_itemid item_id=script_getnum(st,2);
std::shared_ptr<item_data> i_data = item_db.find(item_id);
i_data = itemdb_exists(item_id);
if (i_data)
if (i_data != nullptr)
script_pushint(st,i_data->slots);
else
script_pushint(st,-1);
@@ -16311,18 +16308,19 @@ BUILDIN_FUNC(unequip) {
**/
BUILDIN_FUNC(equip) {
TBL_PC *sd;
struct item_data *item_data;
if (!script_charid2sd(3,sd))
return SCRIPT_CMD_FAILURE;
t_itemid nameid = script_getnum(st,2);
if ((item_data = itemdb_exists(nameid))) {
std::shared_ptr<item_data> id = item_db.find(nameid);
if (id == nullptr) {
int i;
ARR_FIND( 0, MAX_INVENTORY, i, sd->inventory.u.items_inventory[i].nameid == nameid );
if (i < MAX_INVENTORY) {
pc_equipitem(sd,i,item_data->equip);
pc_equipitem(sd,i,id->equip);
script_pushint(st,1);
return SCRIPT_CMD_SUCCESS;
}
@@ -16335,24 +16333,23 @@ BUILDIN_FUNC(equip) {
BUILDIN_FUNC(autoequip)
{
int flag;
struct item_data *item_data;
t_itemid nameid=script_getnum(st,2);
flag=script_getnum(st,3);
int flag=script_getnum(st,3);
std::shared_ptr<item_data> id = item_db.find(nameid);
if( ( item_data = itemdb_exists(nameid) ) == NULL )
if( id == nullptr )
{
ShowError("buildin_autoequip: Invalid item '%u'.\n", nameid);
return SCRIPT_CMD_FAILURE;
}
if( !itemdb_isequip2(item_data) )
if( !itemdb_isequip2(id.get()) )
{
ShowError("buildin_autoequip: Item '%u' cannot be equipped.\n", nameid);
return SCRIPT_CMD_FAILURE;
}
item_data->flag.autoequip = flag>0?1:0;
id->flag.autoequip = flag>0?1:0;
return SCRIPT_CMD_SUCCESS;
}
@@ -17784,14 +17781,14 @@ BUILDIN_FUNC(setitemscript)
{
int n = 0;
const char *script;
struct item_data *i_data;
struct script_code **dstscript;
t_itemid item_id = script_getnum(st,2);
script = script_getstr(st,3);
if( script_hasdata(st,4) )
n=script_getnum(st,4);
i_data = itemdb_exists(item_id);
std::shared_ptr<item_data> i_data = item_db.find(item_id);
if (!i_data || script==NULL || ( script[0] && script[0]!='{' )) {
script_pushint(st,0);
@@ -17845,7 +17842,7 @@ BUILDIN_FUNC(addmonsterdrop)
}
t_itemid item_id = script_getnum(st, 3);
item_data *itm = itemdb_exists(item_id);
std::shared_ptr<item_data> itm = item_db.find(item_id);
if (itm == nullptr) {
ShowError("addmonsterdrop: Nonexistant item %u requested.\n", item_id);
@@ -18085,7 +18082,7 @@ BUILDIN_FUNC(searchitem)
{
struct script_data* data = script_getdata(st, 2);
const char *itemname = script_getstr(st,3);
struct item_data *items[MAX_SEARCH];
std::map<t_itemid, std::shared_ptr<item_data>> items;
int count;
char* name;
@@ -18094,10 +18091,10 @@ BUILDIN_FUNC(searchitem)
int32 i;
TBL_PC* sd = NULL;
if ((items[0] = itemdb_exists(atoi(itemname))))
if ((items[0] = item_db.find(strtoul(itemname, nullptr, 10))))
count = 1;
else
count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname);
count = itemdb_searchname_array(items, MAX_SEARCH, itemname);
if (!count) {
script_pushint(st, 0);
@@ -25208,15 +25205,15 @@ BUILDIN_FUNC(mail){
}
for( i = 0; i < num_items && start < end; i++, start++ ){
struct item_data *item = itemdb_exists(msg.item[i].nameid);
std::shared_ptr<item_data> itm = item_db.find(msg.item[i].nameid);
msg.item[i].amount = (short)get_val2_num( st, reference_uid( id, start ), reference_getref( data ) );
if( msg.item[i].amount <= 0 ){
ShowError( "buildin_mail: amount %d for item %u is invalid.\n", msg.item[i].amount, msg.item[i].nameid );
return SCRIPT_CMD_FAILURE;
}else if( itemdb_isstackable2(item) ){
uint16 max = item->stack.amount > 0 ? item->stack.amount : MAX_AMOUNT;
}else if( itemdb_isstackable2(itm.get()) ){
uint16 max = itm->stack.amount > 0 ? itm->stack.amount : MAX_AMOUNT;
if( msg.item[i].amount > max ){
ShowWarning( "buildin_mail: amount %d for item %u is exceeding the maximum of %d. Capping...\n", msg.item[i].amount, msg.item[i].nameid, max );
@@ -25242,11 +25239,11 @@ BUILDIN_FUNC(mail){
}
for (i = 0; i < num_items && start < end; i++, start++) {
struct item_data* item = itemdb_exists(msg.item[i].nameid);
std::shared_ptr<item_data> itm = item_db.find(msg.item[i].nameid);
msg.item[i].refine = (char)get_val2_num( st, reference_uid( id, start ), reference_getref( data ) );
if (!item->flag.no_refine && (item->type == IT_WEAPON || item->type == IT_ARMOR || item->type == IT_SHADOWGEAR)) {
if (!itm->flag.no_refine && (itm->type == IT_WEAPON || itm->type == IT_ARMOR || itm->type == IT_SHADOWGEAR)) {
if (msg.item[i].refine > MAX_REFINE)
msg.item[i].refine = MAX_REFINE;
}
@@ -25268,8 +25265,6 @@ BUILDIN_FUNC(mail){
}
for( i = 0; i < num_items && start < end; i++, start++ ){
struct item_data *item = itemdb_exists(msg.item[i].nameid);
msg.item[i].bound = (char)get_val2_num( st, reference_uid( id, start ), reference_getref( data ) );
if( msg.item[i].bound < BOUND_NONE || msg.item[i].bound >= BOUND_MAX ){

View File

@@ -24051,7 +24051,7 @@ void SkillDatabase::loadingFinished(){
ShowError( "There are more skills defined in the skill database (%d) than the MAX_SKILL (%d) define. Please increase it and recompile.\n", this->skill_num, MAX_SKILL );
}
TypesafeYamlDatabase::loadingFinished();
TypesafeCachedYamlDatabase::loadingFinished();
}
/**

View File

@@ -3790,10 +3790,10 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
// Check combo items
while (j < item_combo->nameid.size()) {
item_data *id = itemdb_exists(item_combo->nameid[j]);
std::shared_ptr<item_data> id = item_db.find(item_combo->nameid[j]);
// Don't run the script if at least one of combo's pair has restriction
if (id && !pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id, sd->bl.m)) {
if (id && !pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id.get(), sd->bl.m)) {
no_run = true;
break;
}
@@ -3830,7 +3830,6 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
if (sd->inventory_data[index]) {
int j;
struct item_data *data;
// Card script execution.
if (itemdb_isspecial(sd->inventory.u.items_inventory[index].card[0]))
@@ -3840,17 +3839,19 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
current_equip_card_id= c;
if(!c)
continue;
data = itemdb_exists(c);
std::shared_ptr<item_data> data = item_db.find(c);
if(!data)
continue;
if (opt&SCO_FIRST && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {// Execute equip-script on login
if (opt&SCO_FIRST && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data.get(), sd->bl.m))) {// Execute equip-script on login
run_script(data->equip_script,0,sd->bl.id,0);
if (!calculating)
return 1;
}
if(!data->script)
continue;
if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(data,sd->bl.m)) // Card restriction checks.
if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(data.get(), sd->bl.m)) // Card restriction checks.
continue;
if(i == EQI_HAND_L && sd->inventory.u.items_inventory[index].equip == EQP_HAND_L) { // Left hand status.
sd->state.lr_flag = 1;
@@ -3907,7 +3908,8 @@ int status_calc_pc_sub(struct map_session_data* sd, uint8 opt)
}
if (sc->count && sc->data[SC_ITEMSCRIPT]) {
struct item_data *data = itemdb_exists(sc->data[SC_ITEMSCRIPT]->val1);
std::shared_ptr<item_data> data = item_db.find(sc->data[SC_ITEMSCRIPT]->val1);
if (data && data->script)
run_script(data->script, 0, sd->bl.id, 0);
}
@@ -15555,7 +15557,7 @@ void StatusDatabase::loadingFinished(){
}
}
TypesafeYamlDatabase::loadingFinished();
TypesafeCachedYamlDatabase::loadingFinished();
}
StatusDatabase status_db;

View File

@@ -794,19 +794,20 @@ bool storage_guild_additem(struct map_session_data* sd, struct s_storage* stor,
* @return True : success, False : fail
*/
bool storage_guild_additem2(struct s_storage* stor, struct item* item, int amount) {
struct item_data *id;
int i;
nullpo_ret(stor);
nullpo_ret(item);
if (item->nameid == 0 || amount <= 0 || !(id = itemdb_exists(item->nameid)))
if (item->nameid == 0 || amount <= 0)
return false;
if (item->expire_time)
std::shared_ptr<item_data> id = item_db.find(item->nameid);
if (id == nullptr || item->expire_time)
return false;
if (itemdb_isstackable2(id)) { // Stackable
if (itemdb_isstackable2(id.get())) { // Stackable
for (i = 0; i < stor->max_amount; i++) {
if (compare_item(&stor->u.items_guild[i], item)) {
// Set the amount, make it fit with max amount