Initial release of 'itemshop' and 'pointshop'

-- Suggestion: http://rathena.org/board/topic/84169-specialty-shops/
-- Credits: Aleos & Akinari for first diff file that I used to finish this and testing/debugging (well, I don't know the original ones, just tell us or just do pull request if you know the first creator.)
-- How to use?
---> -%TAB%itemshop%TAB%<NPC Name>%TAB%<sprite id>,<costitemid>,<itemid>:<price>{,<itemid>:<price>...}
---> -%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>,<itemid>:<price>{,<itemid>:<price>...}

Signed-off-by: Cahyadi Ramadhan Togihon <house.bad@gmail.com>
This commit is contained in:
Cahyadi Ramadhan Togihon
2013-12-01 00:33:22 +07:00
parent 1d485ca934
commit 32fd3ee303
7 changed files with 189 additions and 62 deletions

View File

@@ -676,10 +676,6 @@
678: You are no longer the Guild Master.
679: You have become the Guild Master!
680: You have been recovered!
681: Item %d has been removed from your inventory.
682: Item %d has been removed from your cart.
683: Item %d has been removed from your storage.
//684-899 free
681: Rune Knight T
682: Warlock T
@@ -707,7 +703,18 @@
706: Player '%s' is now VIP for %d years, %d months, %d days, %d hours and %d minutes.
707: You are VIP until: %s
708: The player is now VIP until: %s
//709-899 free
709: Item %d has been removed from your inventory.
710: Item %d has been removed from your cart.
711: Item %d has been removed from your storage.
//Item shop
712: You do not have enough %s (%d).
713: You do not have enough '%s'.
714: Item Shop List: %s (%d)
715: Point Shop List: '%s'
716: Your '%s' now: %d
//717-899 free
//------------------------------------
// More atcommands message

View File

@@ -268,11 +268,17 @@ normally mean it's pointless since it can't do anything, but there are
exceptions, mostly related to running scripts at specified time, which is what
these floating NPC objects are for. More on that below.
** Define a shop/cashshop NPC.
** Define a shop/cashshop/itemshop/pointshop NPC.
-%TAB%shop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>{,<itemid>:<price>...}
<map name>,<x>,<y>,<facing>%TAB%shop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>{,<itemid>:<price>...}
-%TAB%itemshop%TAB%<NPC Name>%TAB%<sprite id>,<costitemid>,<itemid>:<price>{,<itemid>:<price>...}
<map name>,<x>,<y>,<facing>%TAB%itemshop%TAB%<NPC Name>%TAB%<sprite id>,<costitemid>,<itemid>:<price>{,<itemid>:<price>...}
-%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>,<itemid>:<price>{,<itemid>:<price>...}
<map name>,<x>,<y>,<facing>%TAB%pointshop%TAB%<NPC Name>%TAB%<sprite id>,<costvariable>,<itemid>:<price>{,<itemid>:<price>...}
This will define a shop NPC, which, when triggered (which can only be done by
clicking) will cause a shop window to come up. No code whatsoever runs in shop
NPCs and you can't change the prices otherwise than by editing the script
@@ -291,17 +297,24 @@ This type of shop will not allow you to sell items at it, you may only
purchase items here. The layout used to define sale items still count, and
"<price>" refers to how many points will be spent purchasing the them.
** Define an warp/shop/cashshop/NPC duplicate.
Since trunk rX you can alternatively use "itemshop" or "pointshop" in place
of "shop" to use the Shop interface, allowing you to buy items with a specific
item or special points from a variable. 'pointshop' only supported variable types
are permanent character variables, temporary character variables, permanent
local account variables, or permanent global account variables. These variables
must be of integer type, not string.
** Define an warp/shop/cashshop/itemshop/pointshop/NPC duplicate.
warp: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany>
shop/cashshop/npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
shop/cashshop/itemshop/pointshop/npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
shop/cashshop/itemshop/pointshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
This will duplicate an warp/shop/cashshop/NPC referred to by 'label'.
This will duplicate an warp/shop/cashshop/itemshop/pointshop/NPC referred to by 'label'.
Warp duplicates inherit the target location.
Shop/cashshop duplicates inherit the item list.
Shop/cashshop/itemshop/pointshop duplicates inherit the item list.
NPC duplicates inherit the script code.
The rest (name, location, facing, sprite ID, span/trigger area)
is obtained from the definition of the duplicate (not inherited).

View File

@@ -261,7 +261,7 @@ enum bl_type {
//For common mapforeach calls. Since pets cannot be affected, they aren't included here yet.
#define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM)
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, TOMB };
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, ITEMSHOP, POINTSHOP, TOMB };
enum {
RC_FORMLESS=0,

View File

@@ -12,6 +12,7 @@
#include "../common/db.h"
#include "../common/socket.h"
#include "map.h"
#include "mapreg.h"
#include "log.h"
#include "clif.h"
#include "intif.h"
@@ -1212,11 +1213,28 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
//Hidden/Disabled npc.
if (nd->class_ < 0 || nd->sc.option&(OPTION_INVISIBLE|OPTION_HIDE))
return 1;
switch(nd->subtype) {
case SHOP:
clif_npcbuysell(sd,nd->bl.id);
break;
case ITEMSHOP:
{
char output[CHAT_SIZE_MAX];
struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
memset(output,'\0',sizeof(output));
sprintf(output,msg_txt(sd,714),id->jname,id->nameid); // Item Shop List: %s (%d)
clif_broadcast(&sd->bl,output,strlen(output) + 1,0x10,SELF);
clif_npcbuysell(sd,nd->bl.id);
} break;
case POINTSHOP:
{
char output[CHAT_SIZE_MAX];
memset(output,'\0',sizeof(output));
sprintf(output,msg_txt(sd,715),nd->u.shop.pointshop_str); // Point Shop List: '%s'
clif_broadcast(&sd->bl,output,strlen(output) + 1,0x10,SELF);
clif_npcbuysell(sd,nd->bl.id);
} break;
case CASHSHOP:
clif_cashshop_show(sd,nd);
break;
@@ -1283,7 +1301,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL)
return 1;
if (nd->subtype!=SHOP) {
if (nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP) {
ShowError("no such shop npc : %d\n",id);
if (sd->npc_id == id)
sd->npc_id=0;
@@ -1504,7 +1522,8 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
{
struct npc_data* nd;
double z;
int i,j,w,skill,new_;
int i,j,k,w,skill,new_,count = 0;
char output[CHAT_SIZE_MAX];
nullpo_retr(3, sd);
nullpo_retr(3, item_list);
@@ -1512,7 +1531,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
nd = npc_checknear(sd,map_id2bl(sd->npc_shopid));
if( nd == NULL )
return 3;
if( nd->subtype != SHOP )
if( nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP )
return 3;
z = 0;
@@ -1573,14 +1592,74 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
if( nd->master_nd != NULL ) //Script-based shops.
return npc_buylist_sub(sd,n,item_list,nd->master_nd);
if( z > (double)sd->status.zeny )
return 1; // Not enough Zeny
switch(nd->subtype) {
case SHOP:
if (z > (double)sd->status.zeny)
return 1; // Not enough Zeny
break;
case ITEMSHOP:
for (k = 0; k < MAX_INVENTORY; k++) {
if (sd->status.inventory[k].nameid == nd->u.shop.itemshop_nameid)
count += sd->status.inventory[k].amount;
}
if (z > (double)count) {
struct item_data *id = itemdb_exists(nd->u.shop.itemshop_nameid);
sprintf(output,msg_txt(sd,712),id->jname,id->nameid); // You do not have enough %s %d.
clif_colormes(sd,color_table[COLOR_RED],output);
return 1;
}
break;
case POINTSHOP:
switch(nd->u.shop.pointshop_str[0]) {
case '#':
if (nd->u.shop.pointshop_str[1] == '#')
count = pc_readaccountreg2(sd, nd->u.shop.pointshop_str);
else
count = pc_readaccountreg(sd, nd->u.shop.pointshop_str);
break;
case '@':
default:
count = pc_readglobalreg(sd, nd->u.shop.pointshop_str);
break;
}
if (z > (double)count) {
sprintf(output,msg_txt(sd,713),nd->u.shop.pointshop_str); // You do not have enough '%s'.
clif_colormes(sd,color_table[COLOR_RED],output);
return 1;
}
break;
}
if( w + sd->weight > sd->max_weight )
return 2; // Too heavy
if( pc_inventoryblank(sd) < new_ )
return 3; // Not enough space to store items
pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
switch(nd->subtype) {
case SHOP:
pc_payzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
break;
case ITEMSHOP:
pc_delitem(sd, pc_search_inventory(sd, nd->u.shop.itemshop_nameid), (int)z, 0, 0, LOG_TYPE_NPC);
break;
case POINTSHOP:
switch(nd->u.shop.pointshop_str[0]) {
case '#':
if (nd->u.shop.pointshop_str[1] == '#')
pc_setaccountreg2(sd, nd->u.shop.pointshop_str, count - (int)z);
else
pc_setaccountreg(sd, nd->u.shop.pointshop_str, count - (int)z);
break;
case '@':
default:
pc_setglobalreg(sd, nd->u.shop.pointshop_str, count - (int)z);
break;
}
sprintf(output,msg_txt(sd,716),nd->u.shop.pointshop_str,count - (int)z); // Your '%s' now: %d
clif_disp_onlyself(sd,output,strlen(output)+1);
break;
}
for( i = 0; i < n; ++i )
{
@@ -1688,7 +1767,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
nullpo_retr(1, sd);
nullpo_retr(1, item_list);
if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP )
if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP )
{
return 1;
}
@@ -1857,7 +1936,7 @@ int npc_unload(struct npc_data* nd, bool single) {
}
}
if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
if( (nd->subtype == SHOP || nd->subtype == CASHSHOP || nd->subtype == ITEMSHOP || nd->subtype == POINTSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
aFree(nd->u.shop.shop_item);
else if( nd->subtype == SCRIPT ) {
struct s_mapiterator* iter;
@@ -2195,8 +2274,8 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
//TODO: could be rewritten to NOT need this temp array [ultramage]
#define MAX_SHOPITEM 100
struct npc_item_list items[MAX_SHOPITEM];
char *p;
int x, y, dir, m, i;
char *p, point_str[32];
int x, y, dir, m, i, nameid = 0;
struct npc_data *nd;
enum npc_subtype type;
@@ -2224,40 +2303,76 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
if( !strcasecmp(w2,"cashshop") )
type = CASHSHOP;
else if( !strcasecmp(w2,"itemshop") )
type = ITEMSHOP;
else if( !strcasecmp(w2,"pointshop") )
type = POINTSHOP;
else
type = SHOP;
p = strchr(w4,',');
for( i = 0; i < ARRAYLENGTH(items) && p; ++i )
{
memset(point_str,'\0',sizeof(point_str));
switch(type) {
case ITEMSHOP: {
struct item_data* tmp;
if (sscanf(p,",%d,",&nameid) < 1) {
ShowError("npc_parse_shop: Invalid item cost definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return strchr(start,'\n'); // skip and continue
}
if ((tmp = itemdb_exists(nameid)) == NULL) {
ShowWarning("npc_parse_shop: Invalid item ID cost in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid);
return strchr(start,'\n'); // skip and continue
}
p = strchr(p+1,',');
break;
}
case POINTSHOP: {
if (sscanf(p, ",%32[^,],",point_str) < 1) {
ShowError("npc_parse_shop: Invalid item cost definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return strchr(start,'\n'); // skip and continue
}
switch(point_str[0]) {
case '$':
case '.':
case '\'':
ShowWarning("npc_parse_shop: Invalid item cost variable type (must be permanent character or account based) in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return strchr(start,'\n'); // skip and continue
break;
}
if (point_str[strlen(point_str) - 1] == '$') {
ShowWarning("npc_parse_shop: Invalid item cost variable type (must be integer) in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return strchr(start,'\n'); // skip and continue
}
p = strchr(p+1,',');
break;
}
}
for( i = 0; i < ARRAYLENGTH(items) && p; ++i ) {
int nameid, value;
struct item_data* id;
if( sscanf(p, ",%d:%d", &nameid, &value) != 2 )
{
if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) {
ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
break;
}
if( (id = itemdb_exists(nameid)) == NULL )
{
if( (id = itemdb_exists(nameid)) == NULL ) {
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid);
p = strchr(p+1,',');
continue;
}
if( value < 0 )
{
if( value < 0 ) {
if( type == SHOP ) value = id->value_buy;
else value = 0; // Cashshop doesn't have a "buy price" in the item_db
}
if( type == SHOP && value == 0 )
{ // NPC selling items for free!
if( (type == SHOP || type == ITEMSHOP || type == POINTSHOP) && value == 0 ) { // NPC selling items for free!
ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n",
id->name, nameid, filepath, strline(buffer,start-buffer));
}
if( type == SHOP && value*0.75 < id->value_sell*1.24 )
{// Exploit possible: you can buy and sell back with profit
if( type == SHOP && value*0.75 < id->value_sell*1.24 ) { // Exploit possible: you can buy and sell back with profit
ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
}
@@ -2269,8 +2384,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
items[i].value = value;
p = strchr(p+1,',');
}
if( i == 0 )
{
if( i == 0 ) {
ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// continue
}
@@ -2279,6 +2393,8 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
CREATE(nd->u.shop.shop_item, struct npc_item_list, i);
memcpy(nd->u.shop.shop_item, items, sizeof(struct npc_item_list)*i);
nd->u.shop.count = i;
nd->u.shop.itemshop_nameid = nameid; // Item shop currency
safestrncpy(nd->u.shop.pointshop_str,point_str,strlen(point_str)+1); // Point shop currency
nd->bl.prev = nd->bl.next = NULL;
nd->bl.m = m;
nd->bl.x = x;
@@ -2306,7 +2422,6 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
map_addiddb(&nd->bl);
}
strdb_put(npcname_db, nd->exname, nd);
return strchr(start,'\n');// continue
}
@@ -2592,7 +2707,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
type = dnd->subtype;
// get placement
if( (type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0 ) {// floating shop/chashshop/script
if( (type == SHOP || type == CASHSHOP || type == ITEMSHOP || type == POINTSHOP || type == SCRIPT) && strcmp(w1, "-") == 0 ) {// floating shop/chashshop/itemshop/pointshop/script
x = y = dir = 0;
m = -1;
} else {
@@ -2640,6 +2755,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
case SHOP:
case CASHSHOP:
case ITEMSHOP:
case POINTSHOP:
++npc_shop;
nd->u.shop.shop_item = dnd->u.shop.shop_item;
nd->u.shop.count = dnd->u.shop.count;
@@ -3642,34 +3759,22 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
}
if( strcasecmp(w2,"warp") == 0 && count > 3 )
{
p = npc_parse_warp(w1,w2,w3,w4, p, buffer, filepath);
}
else if( (!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop")) && count > 3 )
{
else if( (!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop") || !strcasecmp(w2,"itemshop") || !strcasecmp(w2,"pointshop")) && count > 3 )
p = npc_parse_shop(w1,w2,w3,w4, p, buffer, filepath);
}
else if( strcasecmp(w2,"script") == 0 && count > 3 )
{
else if( strcasecmp(w2,"script") == 0 && count > 3 ) {
if( strcasecmp(w1,"function") == 0 )
p = npc_parse_function(w1, w2, w3, w4, p, buffer, filepath);
else
p = npc_parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit);
}
else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 )
{
p = npc_parse_duplicate(w1,w2,w3,w4, p, buffer, filepath);
}
else if( (strcmpi(w2,"monster") == 0 || strcmpi(w2,"boss_monster") == 0) && count > 3 )
{
p = npc_parse_mob(w1, w2, w3, w4, p, buffer, filepath);
}
else if( strcmpi(w2,"mapflag") == 0 && count >= 3 )
{
p = npc_parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath);
}
else
{
else {
ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
p = strchr(p,'\n');// skip and continue
}

View File

@@ -58,6 +58,8 @@ struct npc_data {
struct {
struct npc_item_list* shop_item;
int count;
int itemshop_nameid; // Item Shop cost item ID
char pointshop_str[32]; // Point Shop cost variable name
} shop;
struct {
short xs,ys; // OnTouch area radius

View File

@@ -9075,7 +9075,7 @@ int pc_check_available_item(struct map_session_data *sd) {
it = sd->status.inventory[i].nameid;
if( it && !itemdb_available(it) ) {
sprintf(output, msg_txt(sd, 681), it); // Item %d has been removed from your inventory.
sprintf(output, msg_txt(sd, 709), it); // Item %d has been removed from your inventory.
clif_displaymessage(sd->fd, output);
ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", it, sd->status.inventory[i].amount, sd->status.char_id);
pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
@@ -9088,7 +9088,7 @@ int pc_check_available_item(struct map_session_data *sd) {
it = sd->status.cart[i].nameid;
if( it && !itemdb_available(it) ) {
sprintf(output, msg_txt(sd, 682), it); // Item %d has been removed from your cart.
sprintf(output, msg_txt(sd, 710), it); // Item %d has been removed from your cart.
clif_displaymessage(sd->fd, output);
ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", it, sd->status.cart[i].amount, sd->status.char_id);
pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER);
@@ -9101,7 +9101,7 @@ int pc_check_available_item(struct map_session_data *sd) {
it = sd->status.storage.items[i].nameid;
if( it && !itemdb_available(it) ) {
sprintf(output, msg_txt(sd, 683), it); // Item %d has been removed from your storage.
sprintf(output, msg_txt(sd, 711), it); // Item %d has been removed from your storage.
clif_displaymessage(sd->fd, output);
ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", it, sd->status.storage.items[i].amount, sd->status.char_id);
storage_delitem(sd, i, sd->status.storage.items[i].amount);

View File

@@ -14955,14 +14955,14 @@ BUILDIN_FUNC(callshop)
if( script_hasdata(st,3) )
flag = script_getnum(st,3);
nd = npc_name2id(shopname);
if( !nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP) )
if( !nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP) )
{
ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname);
script_pushint(st,0);
return 1;
}
if( nd->subtype == SHOP )
if( nd->subtype == SHOP || nd->subtype == ITEMSHOP || nd->subtype == POINTSHOP )
{
// flag the user as using a valid script call for opening the shop (for floating NPCs)
sd->state.callshop = 1;
@@ -14989,7 +14989,7 @@ BUILDIN_FUNC(npcshopitem)
int n, i;
int amount;
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;
@@ -15018,7 +15018,7 @@ BUILDIN_FUNC(npcshopadditem)
int n, i;
int amount;
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;
@@ -15049,7 +15049,7 @@ BUILDIN_FUNC(npcshopdelitem)
int amount;
int size;
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;