see in docs for NST_CUSTOM
yes master but i wanted to use that LIMITED QTY feature but uses #CASHPOINTS instead of Zeny
i tried already
/**
* Processes incoming npc market purchase list
**/
static enum market_buy_result npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
{
struct npc_data* nd;
struct npc_item_list *shop = NULL;
int64 z;
int i,j,w,new_;
unsigned short shop_size = 0;
nullpo_retr(1, sd);
nullpo_retr(1, item_list);
nd = npc->checknear(sd,map->id2bl(sd->npc_shopid));
if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET)
return MARKET_BUY_RESULT_ERROR;
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
z = 0;
w = 0;
new_ = 0;
// process entries in buy list, one by one
for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
int value;
struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
// find this entry in the shop's sell list
ARR_FIND( 0, shop_size, j,
entry->id == shop[j].nameid || //Normal items
entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement
);
if (j == shop_size) /* TODO find official response for this */
return MARKET_BUY_RESULT_ERROR; // no such item in shop
entry->id = shop[j].nameid; //item_avail replacement
if (entry->amount > (int)shop[j].qty)
return MARKET_BUY_RESULT_AMOUNT_TOO_BIG;
value = shop[j].value;
npc_market_qty
= j;
if (!itemdb->exists(entry->id)) /* TODO find official response for this */
return MARKET_BUY_RESULT_ERROR; // item no longer in itemdb
if (!itemdb->isstackable(entry->id) && entry->amount > 1) {
//Exploit? You can't buy more than 1 of equipment types 
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, entry->amount, entry->id);
entry->amount = 1;
}
switch (pc->checkadditem(sd, entry->id, entry->amount)) {
case ADDITEM_EXIST:
break;
case ADDITEM_NEW:
new_++;
break;
case ADDITEM_OVERAMOUNT: /* TODO find official response for this */
return 1;
}
z += (int64)value * entry->amount;
w += itemdb_weight(entry->id) * entry->amount;
}
if (z > sd->cashPoints) /* TODO find official response for this */
return MARKET_BUY_RESULT_NO_ZENY; // Not enough Zeny
if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */
return MARKET_BUY_RESULT_OVER_WEIGHT; // Too heavy
if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */
return MARKET_BUY_RESULT_OUT_OF_SPACE; // Not enough space to store items
pc->paycash(sd,(int)z,0);
for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
j = npc_market_qty;
if (entry->amount > (int)shop[j].qty) /* wohoo someone tampered with the packet. */
return MARKET_BUY_RESULT_AMOUNT_TOO_BIG;
shop[j].qty -= entry->amount;
npc->market_tosql(nd,j);
if (itemdb_type(entry->id) == IT_PETEGG) {
pet->create_egg(sd, entry->id);
} else {
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = entry->id;
item_tmp.identify = 1;
pc->additem(sd, &item_tmp, entry->amount, LOG_TYPE_NPC);
}
}
return MARKET_BUY_RESULT_SUCCESS;
}
if (z > sd->cashPoints) /* TODO find official response for this */
It's working ok by deducting CP. It still check zeny when you drag item to buy.