summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c277
1 files changed, 276 insertions, 1 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 074348ef0..a9ad69954 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2072,7 +2072,7 @@ void script_set_constant2(const char *name, int value, bool isparameter) {
int n = script->add_str(name);
if( ( script->str_data[n].type == C_NAME || script->str_data[n].type == C_PARAM ) && ( script->str_data[n].val != 0 || script->str_data[n].backpatch != -1 ) ) { // existing parameter or constant
- ShowNotice("Conflicting item/script var '%s', prioritising the script var\n",name);
+ ShowNotice("Conflicting var name '%s', prioritising the script var\n",name);
return;
}
@@ -18012,6 +18012,272 @@ BUILDIN(instance_set_respawn) {
return true;
}
+/**
+ * @call openshop({NPC Name});
+ *
+ * @return 1 on success, 0 otherwise.
+ **/
+BUILDIN(openshop) {
+ struct npc_data *nd;
+ struct map_session_data *sd;
+ const char *name = NULL;
+
+ if( script_hasdata(st, 2) ) {
+ name = script_getstr(st, 2);
+ if( !(nd = npc->name2id(name)) || nd->subtype != SCRIPT ) {
+ ShowWarning("buildin_openshop(\"%s\"): trying to run without a proper NPC!\n",name);
+ return false;
+ }
+ } else if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_openshop: trying to run without a proper NPC!\n");
+ return false;
+ }
+ if( !( sd = script->rid2sd(st) ) ) {
+ ShowWarning("buildin_openshop: trying to run without a player attached!\n");
+ return false;
+ } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) {
+ ShowWarning("buildin_openshop: trying to open without any items!\n");
+ return false;
+ }
+
+ if( !npc->trader_open(sd,nd) )
+ script_pushint(st, 0);
+ else
+ script_pushint(st, 1);
+
+ return true;
+}
+/**
+ * @call sellitem <Item_ID>,{,price{,qty}};
+ *
+ * adds <Item_ID> (or modifies if present) to shop
+ * if price not provided (or -1) uses the item's value_sell
+ **/
+BUILDIN(sellitem) {
+ struct npc_data *nd;
+ struct item_data *it;
+ int i = 0, id = script_getnum(st,2);
+ int value = 0;
+ int qty = 0;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_sellitem: trying to run without a proper NPC!\n");
+ return false;
+ } else if ( !(it = itemdb->exists(id)) ) {
+ ShowWarning("buildin_sellitem: unknown item id '%d'!\n",id);
+ return false;
+ }
+
+ value = script_hasdata(st,3) ? script_getnum(st, 3) : it->value_buy;
+ if( value == -1 )
+ value = it->value_buy;
+
+ if( !nd->u.scr.shop )
+ npc->trader_update(nd->src_id?nd->src_id:nd->bl.id);
+ else {/* no need to run this if its empty */
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == id )
+ break;
+ }
+ }
+
+ if( nd->u.scr.shop->type == NST_MARKET ) {
+ if( !script_hasdata(st,4) || ( qty = script_getnum(st, 4) ) <= 0 ) {
+ ShowError("buildin_sellitem: invalid 'qty' for market-type shop!\n");
+ return false;
+ }
+ }
+
+ if( ( nd->u.scr.shop->type == NST_ZENY || nd->u.scr.shop->type == NST_MARKET ) && value*0.75 < it->value_sell*1.24 ) {
+ ShowWarning("buildin_sellitem: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in NPC %s (%s)\n",
+ it->name, id, value, (int)(value*0.75), it->value_sell, (int)(it->value_sell*1.24), nd->exname, nd->path);
+ }
+
+ if( i != nd->u.scr.shop->items ) {
+ nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].qty = qty;
+ if( nd->u.scr.shop->type == NST_MARKET ) /* has been manually updated, make it reflect on sql */
+ npc->market_tosql(nd,i);
+ } else {
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == 0 )
+ break;
+ }
+
+ if( i == nd->u.scr.shop->items ) {
+ if( nd->u.scr.shop->items == USHRT_MAX ) {
+ ShowWarning("buildin_sellitem: Can't add %s (%s/%s), shop list is full!\n", it->name, nd->exname, nd->path);
+ return false;
+ }
+ i = nd->u.scr.shop->items;
+ RECREATE(nd->u.scr.shop->item, struct npc_item_list, ++nd->u.scr.shop->items);
+ }
+
+ nd->u.scr.shop->item[i].nameid = it->nameid;
+ nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].qty = qty;
+ }
+
+ return true;
+}
+/**
+ * @call stopselling <Item_ID>;
+ *
+ * removes <Item_ID> from the current npc shop
+ *
+ * @return 1 on success, 0 otherwise
+ **/
+BUILDIN(stopselling) {
+ struct npc_data *nd;
+ int i, id = script_getnum(st,2);
+
+ if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ ShowWarning("buildin_stopselling: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == id )
+ break;
+ }
+
+ if( i != nd->u.scr.shop->items ) {
+ int cursor;
+
+ if( nd->u.scr.shop->type == NST_MARKET )
+ npc->market_delfromsql(nd,i);
+
+ nd->u.scr.shop->item[i].nameid = 0;
+ nd->u.scr.shop->item[i].value = 0;
+ nd->u.scr.shop->item[i].qty = 0;
+
+ for( i = 0, cursor = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == 0 )
+ continue;
+
+ if( cursor != i ) {
+ nd->u.scr.shop->item[cursor].nameid = nd->u.scr.shop->item[i].nameid;
+ nd->u.scr.shop->item[cursor].value = nd->u.scr.shop->item[i].value;
+ nd->u.scr.shop->item[cursor].qty = nd->u.scr.shop->item[i].qty;
+ }
+
+ cursor++;
+ }
+
+ script_pushint(st, 1);
+ } else
+ script_pushint(st, 0);
+
+ return true;
+}
+/**
+ * @call setcurrency <Val1>{,<Val2>};
+ *
+ * updates currently-attached player shop currency
+ **/
+/* setcurrency(<Val1>,{<Val2>}) */
+BUILDIN(setcurrency) {
+ int val1 = script_getnum(st,2),
+ val2 = script_hasdata(st, 3) ? script_getnum(st,3) : 0;
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_setcurrency: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ npc->trader_funds[0] = val1;
+ npc->trader_funds[1] = val2;
+
+ return true;
+}
+/**
+ * @call tradertype(<type>);
+ *
+ * defaults to 0, so no need to call when you're doing zeny
+ * check enum npc_shop_types for list
+ * cleans shop list on use
+ **/
+BUILDIN(tradertype) {
+ int type = script_getnum(st, 2);
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_tradertype: trying to run without a proper NPC!\n");
+ return false;
+ } else if ( type < 0 || type > NST_MAX ) {
+ ShowWarning("buildin_tradertype: invalid type param %d!\n",type);
+ return false;
+ }
+
+ if( !nd->u.scr.shop )
+ npc->trader_update(nd->src_id?nd->src_id:nd->bl.id);
+ else {/* clear list */
+ int i;
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ nd->u.scr.shop->item[i].nameid = 0;
+ nd->u.scr.shop->item[i].value = 0;
+ nd->u.scr.shop->item[i].qty = 0;
+ }
+ npc->market_delfromsql(nd,USHRT_MAX);
+ }
+
+ nd->u.scr.shop->type = type;
+
+ return true;
+}
+/**
+ * @call purchaseok();
+ *
+ * signs the transaction can proceed
+ **/
+BUILDIN(purchaseok) {
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ ShowWarning("buildin_purchaseok: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ npc->trader_ok = true;
+
+ return true;
+}
+/**
+ * @call shopcount(<Item_ID>);
+ *
+ * @return number of available items in the script's attached shop
+ **/
+BUILDIN(shopcount) {
+ struct npc_data *nd;
+ int id = script_getnum(st, 2);
+ unsigned short i;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_shopcount(%d): trying to run without a proper NPC!\n",id);
+ return false;
+ } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) {
+ ShowWarning("buildin_shopcount(%d): trying to use without any items!\n",id);
+ return false;
+ } else if ( nd->u.scr.shop->type != NST_MARKET ) {
+ ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET shop!\n",id);
+ return false;
+ }
+
+ /* lookup */
+ for(i = 0; i < nd->u.scr.shop->items; i++) {
+ if( nd->u.scr.shop->item[i].nameid == id ) {
+ script_pushint(st, nd->u.scr.shop->item[i].qty);
+ break;
+ }
+ }
+
+ /* didn't find it */
+ if( i == nd->u.scr.shop->items )
+ script_pushint(st, 0);
+
+ return true;
+}
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
@@ -18609,6 +18875,15 @@ void script_parse_builtin(void) {
BUILDIN_DEF(bg_create_team,"sii"),
BUILDIN_DEF(bg_join_team,"i?"),
BUILDIN_DEF(bg_match_over,"s?"),
+
+ /* New Shop Support */
+ BUILDIN_DEF(openshop,"?"),
+ BUILDIN_DEF(sellitem,"i??"),
+ BUILDIN_DEF(stopselling,"i"),
+ BUILDIN_DEF(setcurrency,"i?"),
+ BUILDIN_DEF(tradertype,"i"),
+ BUILDIN_DEF(purchaseok,""),
+ BUILDIN_DEF(shopcount, "i"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up