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.c227
1 files changed, 182 insertions, 45 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 25bf59839..24cb8e4f4 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -4621,6 +4621,9 @@ static void run_script_main(struct script_state *st)
nullpo_retv(st);
script->attach_state(st);
+ if (st->state != END && Assert_chk(st->state == RUN || st->state == STOP || st->state == RERUNLINE)) {
+ st->state = END;
+ }
nd = map->id2nd(st->oid);
if( nd && nd->bl.m >= 0 )
@@ -7637,6 +7640,65 @@ static BUILDIN(countitem2)
}
/*==========================================
+ * countnameditem(item ID, { <Char Name / ID> })
+ * returns number of named items.
+ *------------------------------------------*/
+static BUILDIN(countnameditem)
+{
+ int count = 0;
+ struct item_data* id = NULL;
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 3)) {
+ if (script_isstringtype(st, 3)) {
+ // Character name was given
+ sd = script->nick2sd(st, script_getstr(st, 3));
+ } else {
+ // Character ID was given
+ sd = script->charid2sd(st, script_getnum(st, 3));
+ }
+ } else {
+ // Use RID by default if no name was provided
+ sd = script->rid2sd(st);
+ }
+
+ // Player not attached
+ if (sd == NULL) {
+ return true;
+ }
+
+ if (script_isstringtype(st, 2)) {
+ // Get item from DB via item name
+ id = itemdb->search_name(script_getstr(st, 2));
+ } else {
+ // Get item from DB via item ID
+ id = itemdb->exists(script_getnum(st, 2));
+ }
+
+ if (id == NULL) {
+ ShowError("buildin_countnameditem: Invalid item '%s'.\n", script_getstr(st, 2)); // returns string, regardless of what it was
+ script_pushint(st, 0);
+ return false;
+ }
+
+ for (int i = 0; i < MAX_INVENTORY; i++) {
+ if (sd->status.inventory[i].nameid > 0 &&
+ sd->inventory_data[i] != NULL &&
+ sd->status.inventory[i].amount > 0 &&
+ sd->status.inventory[i].nameid == id->nameid &&
+ sd->status.inventory[i].card[0] == CARD0_CREATE &&
+ sd->status.inventory[i].card[2] == sd->status.char_id &&
+ sd->status.inventory[i].card[3] == sd->status.char_id >> 16)
+ {
+ count += sd->status.inventory[i].amount;
+ }
+ }
+
+ script_pushint(st, count);
+ return true;
+}
+
+/*==========================================
* Check if item with this amount can fit in inventory
* Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY)
* Return
@@ -10671,7 +10733,7 @@ static BUILDIN(makepet)
if (pet_id >= 0 && sd) {
sd->catch_target_class = pet->db[pet_id].class_;
intif->create_pet(sd->status.account_id, sd->status.char_id,
- (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv,
+ pet->db[pet_id].class_, mob->db(pet->db[pet_id].class_)->lv,
pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
100, 0, 1, pet->db[pet_id].jname);
}
@@ -19705,7 +19767,7 @@ static BUILDIN(getunitdata)
if (bl == NULL) {
ShowWarning("buildin_getunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2));
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
@@ -19714,7 +19776,7 @@ static BUILDIN(getunitdata)
/* Type check */
if (type < UDT_TYPE || type >= UDT_MAX) {
ShowError("buildin_getunitdata: Invalid unit data type %d provided.\n", type);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
@@ -19722,7 +19784,7 @@ static BUILDIN(getunitdata)
if (type == UDT_MAPIDXY) {
if (data == NULL || !data_isreference(data)) {
ShowWarning("buildin_getunitdata: Error in argument 3. Please provide a reference variable to store values in.\n");
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
@@ -19732,7 +19794,7 @@ static BUILDIN(getunitdata)
sd = script->rid2sd(st);
if (sd == NULL) {
ShowWarning("buildin_getunitdata: Player not attached! Cannot use player variable %s.\n",name);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return true;// no player attached
}
}
@@ -19802,7 +19864,7 @@ static BUILDIN(getunitdata)
case UDT_DMOTION: script_pushint(st, md->status.dmotion); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mob unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
@@ -19859,7 +19921,7 @@ static BUILDIN(getunitdata)
case UDT_INTIMACY: script_pushint(st, hd->homunculus.intimacy); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for Homunculus unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
@@ -19916,7 +19978,7 @@ static BUILDIN(getunitdata)
case UDT_INTIMACY: script_pushint(st, pd->pet.intimate); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for Pet unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
@@ -19972,7 +20034,7 @@ static BUILDIN(getunitdata)
case UDT_LIFETIME: script_pushint(st, mc->mercenary.life_time); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mercenary unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
@@ -20026,7 +20088,7 @@ static BUILDIN(getunitdata)
case UDT_MASTERCID: script_pushint(st, ed->elemental.char_id); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for Elemental unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
@@ -20091,14 +20153,14 @@ static BUILDIN(getunitdata)
case UDT_BODY2: script_pushint(st, nd->vd.body_style); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for NPC unit.\n", udtype);
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
}
}
break;
default:
ShowError("buildin_getunitdata: Unknown object!\n");
- script_pushint(st, 0);
+ script_pushint(st, -1);
return false;
} // end of bl->type switch
@@ -23878,6 +23940,7 @@ static BUILDIN(sellitem)
struct item_data *it;
int i = 0, id = script_getnum(st,2);
int value = 0;
+ int value2 = 0;
int qty = 0;
if( !(nd = map->id2nd(st->oid)) ) {
@@ -23888,17 +23951,43 @@ static BUILDIN(sellitem)
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) {
+ npc->trader_update(nd->src_id ? nd->src_id : nd->bl.id);
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ if (!script_hasdata(st, 5)) {
+ ShowError("buildin_sellitem: invalid number of parameters for barter-type shop!\n");
+ return false;
+ }
+ value = script_getnum(st, 4);
+ value2 = script_getnum(st, 5);
}
+ } else {/* no need to run this if its empty */
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ if (!script_hasdata(st, 5)) {
+ ShowError("buildin_sellitem: invalid number of parameters for barter-type shop!\n");
+ return false;
+ }
+ value = script_getnum(st, 4);
+ value2 = script_getnum(st, 5);
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == id && item->value == value && item->value2 == value2) {
+ break;
+ }
+ }
+ } else {
+ 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_BARTER) {
+ value = script_hasdata(st,3) ? script_getnum(st, 3) : it->value_buy;
+ if( value == -1 )
+ value = it->value_buy;
}
if( nd->u.scr.shop->type == NST_MARKET ) {
@@ -23913,19 +24002,29 @@ static BUILDIN(sellitem)
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 ) {
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ qty = script_getnum(st, 3);
+ if (qty < -1 || value <= 0 || value2 <= 0) {
+ ShowError("buildin_sellitem: invalid parameters for barter-type shop!\n");
+ return false;
+ }
+ }
+
+ 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);
+ if (nd->u.scr.shop->type == NST_MARKET) /* has been manually updated, make it reflect on sql */
+ npc->market_tosql(nd, i);
+ else if (nd->u.scr.shop->type == NST_BARTER) /* has been manually updated, make it reflect on sql */
+ npc->barter_tosql(nd, i);
} else {
- for( i = 0; i < nd->u.scr.shop->items; i++ ) {
- if( nd->u.scr.shop->item[i].nameid == 0 )
+ 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 ) {
+ 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;
}
@@ -23935,6 +24034,7 @@ static BUILDIN(sellitem)
nd->u.scr.shop->item[i].nameid = it->nameid;
nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].value2 = value2;
nd->u.scr.shop->item[i].qty = qty;
}
@@ -23951,35 +24051,55 @@ static BUILDIN(sellitem)
static BUILDIN(stopselling)
{
struct npc_data *nd;
- int i, id = script_getnum(st,2);
+ int i, id = script_getnum(st, 2);
- if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ 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 (nd->u.scr.shop->type == NST_BARTER) {
+ if (!script_hasdata(st, 4)) {
+ ShowError("buildin_stopselling: called with wrong number of arguments\n");
+ return false;
+ }
+ const int id2 = script_getnum(st, 3);
+ const int amount2 = script_getnum(st, 4);
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == id && item->value == id2 && item->value2 == amount2) {
+ break;
+ }
+ }
+ } else {
+ 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 ) {
+ if (i != nd->u.scr.shop->items) {
int cursor;
- if( nd->u.scr.shop->type == NST_MARKET )
- npc->market_delfromsql(nd,i);
+ if (nd->u.scr.shop->type == NST_MARKET)
+ npc->market_delfromsql(nd, i);
+ if (nd->u.scr.shop->type == NST_BARTER)
+ npc->barter_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].value2 = 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 )
+ 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 ) {
+ 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].value2 = nd->u.scr.shop->item[i].value2;
nd->u.scr.shop->item[cursor].qty = nd->u.scr.shop->item[i].qty;
}
@@ -24045,7 +24165,8 @@ static BUILDIN(tradertype)
nd->u.scr.shop->item[i].value = 0;
nd->u.scr.shop->item[i].qty = 0;
}
- npc->market_delfromsql(nd,USHRT_MAX);
+ npc->market_delfromsql(nd, INT_MAX);
+ npc->barter_delfromsql(nd, INT_MAX);
}
#if PACKETVER < 20131223
@@ -24054,6 +24175,12 @@ static BUILDIN(tradertype)
script->reportsrc(st);
}
#endif
+#if PACKETVER_MAIN_NUM < 20190116 && PACKETVER_RE_NUM < 20190116 && PACKETVER_ZERO_NUM < 20181226
+ if (type == NST_BARTER) {
+ ShowWarning("buildin_tradertype: NST_BARTER is only available with PACKETVER_ZERO_NUM 20181226 or PACKETVER_MAIN_NUM 20190116 or PACKETVER_RE_NUM 20190116 or newer!\n");
+ script->reportsrc(st);
+ }
+#endif
if( nd->u.scr.shop )
nd->u.scr.shop->type = type;
@@ -24097,8 +24224,8 @@ static BUILDIN(shopcount)
} 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);
+ } else if (nd->u.scr.shop->type != NST_MARKET && nd->u.scr.shop->type != NST_BARTER) {
+ ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET and non-NST_BARTER shop!\n",id);
return false;
}
@@ -25135,6 +25262,7 @@ static void script_parse_builtin(void)
BUILDIN_DEF(rand,"i?"),
BUILDIN_DEF(countitem,"v"),
BUILDIN_DEF(countitem2,"viiiiiii"),
+ BUILDIN_DEF(countnameditem,"v?"),
BUILDIN_DEF(checkweight,"vi*"),
BUILDIN_DEF(checkweight2,"rr"),
BUILDIN_DEF(readparam,"i?"),
@@ -25623,8 +25751,8 @@ static void script_parse_builtin(void)
/* New Shop Support */
BUILDIN_DEF(openshop,"?"),
- BUILDIN_DEF(sellitem,"i??"),
- BUILDIN_DEF(stopselling,"i"),
+ BUILDIN_DEF(sellitem,"i???"),
+ BUILDIN_DEF(stopselling,"i??"),
BUILDIN_DEF(setcurrency,"i?"),
BUILDIN_DEF(tradertype,"i"),
BUILDIN_DEF(purchaseok,""),
@@ -25717,6 +25845,8 @@ static void script_hardcoded_constants(void)
script->set_constant("MAX_REFINE",MAX_REFINE,false, false);
script->set_constant("MAX_MENU_OPTIONS", MAX_MENU_OPTIONS, false, false);
script->set_constant("MAX_MENU_LENGTH", MAX_MENU_LENGTH, false, false);
+ script->set_constant("MOB_CLONE_START", MOB_CLONE_START, false, false);
+ script->set_constant("MOB_CLONE_END", MOB_CLONE_END, false, false);
script->constdb_comment("status options");
script->set_constant("Option_Nothing",OPTION_NOTHING,false, false);
@@ -26105,6 +26235,13 @@ static void script_hardcoded_constants(void)
script->set_constant("EXPAND_INV_RESULT_MISSING_ITEM", EXPAND_INVENTORY_RESULT_MISSING_ITEM, false, false);
script->set_constant("EXPAND_INV_RESULT_MAX_SIZE", EXPAND_INVENTORY_RESULT_MAX_SIZE, false, false);
+ script->constdb_comment("trader type");
+ script->set_constant("NST_ZENY", NST_ZENY, false, false);
+ script->set_constant("NST_CASH", NST_CASH, false, false);
+ script->set_constant("NST_MARKET", NST_MARKET, false, false);
+ script->set_constant("NST_CUSTOM", NST_CUSTOM, false, false);
+ script->set_constant("NST_BARTER", NST_BARTER, false, false);
+
script->constdb_comment("Renewal");
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false, false);