diff options
Diffstat (limited to 'src/map/script.c')
-rw-r--r-- | src/map/script.c | 227 |
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); |